java复习系列之封装、继承和多态

面向对象的三大特性:封装、继承和多态

封装

封装的好处:

可以将类的属性分为私有和公有属性,私有属性只在本类中调用,公有属性也只提供给外调用的方法;保留调用方法不变的同时,类内部的结构是可以自由修改,而不会影响到调用者的运行结果;同时内部还可以进行一下验证性的修改,同样也不会印象调用者的运行结果。

继承

继承的好处:

提高了代码的复用性,也正是因为有了继承,才会有多态的存在。需要注意的是Java只支持单继承,不支持多继承,这点理解起来很简单,如果多个父类中定义了相同的方法,但是功能不一样的情况下,那子类就懵了,到底是用哪一个方法呢。所以java中是没有多继承的,但是java可以通过多实现来解决多继承问题。

继承后子父类成员的特点
变量的特点:

父类的成员变量私有化之后,子类依然继承,但不能直接访问。

如果子类中出现非私有的同名成员变量时,本类要访问本类中的变量用 this ,要访问父类中的同名变量,用super。

举例如下:Fu类有2个成员变量,一个私有一个公有。

public class Fu {
	private int i = 1;
	public int j = 2;
}
Zi类继承Fu类,子类有和Fu类同名的成员变量j,从编译和运行结果可以看出继承之后成员变量的特点。
public class Zi extends Fu{

	public int j = 3;
	public static void main(String[] args) {
		new Zi().method();
	}
	private void method() {
//		System.out.println(i);//编译不通过
//		System.out.println(super.i);//编译不通过
		System.out.println(j);//输出3
		System.out.println(super.j);//输出2
		System.out.println(this.j);//输出3
	}
}

函数的特点

当子类中出现和父类一模一样的函数A时,当子类对象调用函数A,会运行子类函数的内容,父类中的函数会被重写。如果需要调用父类的方法时,需要使用super。

举例:Fu类中有方法Method(),

public class Fu {
	public  int j = 2;
	public void Method() {
		System.out.println("Fu");
	}
}
子类中也有方法Method()
public class Zi extends Fu {
	public int j = 3;
	public static void main(String[] args) {
		new Zi().Method();
	}
	public void Method() {
		super.Method();//输出Fu
		System.out.println("Zi");//输出Zi
	}
}
从输出结果看看看出,需要调用父类的方法需要使用关键字super。

另外注意关键字super和this一样指的是类的具体对象的引用,二使用static关键字修饰过的变量或者方法,是和类本身相关的,所以如果这个时候使用this或者super去调用的话,那么编译不会通过,会抛出异常Cannot use this in a static context或者Cannot use super in a static context的异常。
关于重写(覆盖)的几点说明:

1)子类覆盖父类,必须保证子类权限大于等于父类权限,才能重写 。可以简单的理解为重写的目的是为了程序更方便高效,假设重写之后限制更多,实用性更差,那么还有什么必要去重写一个方法呢。所以必须保证子类的权限要大于父类的权限;

2)子类覆盖父类,必须保证子类抛出的异常小于父类抛出的异常。这个的理解参照上面一样的理解就好了。

这里在啰嗦一下重写和重载之间的区别:

重载:只看同名函数的参数列表,即参数的个数,位置不一样的都是重载。

重写:名字返回值类型参数等都要一样才是重写。

构造函数的特点

在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数会隐式调用父类的空参构造函数(即super())。当父类中没有空参数的构造函数时,子类必须手动通过super语句的形式来指定要访问父类中的构造函数。当然子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,子类中至少会有一个构造函数会访问父类中的构造函数。

举例如下:Fu类定义了一个有参数的构造方法。

public class Fu {
	Fu(int m){//注意此处没有默认的构造函数了
		System.out.println("Fu"+m);
	}
}

Zi类中有两个构造方法,一个有参数一个没有参数,

public class Zi extends Fu {
	Zi() {
		// 此处必须手动调用Fu类构造方法,或者调用本类中的构造方法,如果调用本类中的构造方法,那么其他的构造方法至少要有
		// 一个调用父类的构造方法,否则编译报错Implicit super constructor Fu() is undefined. Must
		// explicitly invoke another constructor
		System.out.println("Zi");
	}

	Zi(int i) {
		// 同上
		System.out.println("Zi" + i);
	}

	public static void main(String[] args) {
		new Zi();
		new Zi(3);
	}
}

多态

多态的好处是提高了程序的扩展性,但是有一个前提条件,就是之前说过的,有继承或者实现才有多态的体现,多态体现在父类的引用指向子类的对象。

这里可以参考一个多态的经典例子:

http://blog.csdn.net/free4294/article/details/39054791

个人感觉这个例子中的问题,在实际上是很难遇到的,但是既然看到这个问题了,还是有必要去了解一下的,根据例子中给出的解释:实际上这里涉及方法调用的优先问题 ,优先级由高到低依次为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。虽然这种顺序是能解释这个问题的,但是关于这个顺序目前没有在其他书籍和文献助攻看到过,这里暂且记下,以后看到了在回过头来补充补充。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值