前言:
封装:通过合并特征和行为创建新的数据类型。
实现隐藏:通过将细节“私有化”,把接口和实现分离。
多态:消除类型间的耦合关系。也称作动态绑定,后期绑定或运行时绑定。
8.1再论向上转型:
对象既可以作为本身的类型使用,也可以作为基类的类型使用。这种做法成为向上转型。
其代码表现就是:父类引用指向子类。
多态允许在参数的地方使用,即参数处声明基类,用于接受基类或导出类实现。
8.2转机(主要是介绍如何实现多态)
为了解决多态问题,在java中提供了后期绑定的方法,即在运行时根据对象的类型进行绑定。也成为动态绑定或运行时绑定。
注:java中除了static方法和final方法,其他方法都是后期绑定。final关键字可以关闭动态绑定。
final关键字最好根据设计来决定是否使用。千万不能通过final来提高性能,因为并不会提升性能,而且也会让程序的设计显得混乱。
多态可以让程序员将:改变的事物与未变的事物分离开来。
这里再次提高了试图重写基类的private方法是一种很错误的行为。
只有普通方法的调用是多态的,静态方法不具有多态性(实际上final也没有,而且由于private隐式指向final,所以也没有)。
8.3构造器与多态
构造器是不具有多态的,他们本质上是static方法,只不过是隐式声明。
前面提到过:基类的构造器总是在导出类的构造过程中被调用,且按照继承层次逐渐向上调用。
对于复杂的继承体系:
1)调用基类的构造器
2)按声明顺序调用成员变量的初始化方法。
3)调用导出类的构造器本体。
注:继承体系中,为什么这样调用?因为在导出类中要求基类是已经存在的,且基类的一切成员(public protect)都可以访问到。
涉及到内存方面的构造过程:
1)将分配给对象的存储空间初始化成二进制的零。
2)调用基类构造器。
3)按照声明的顺序调用成员的初始化方法。
4)调用导出类的构造器主体。
实际上构造器中,除了初始化成员外,唯一能够安全调用的方法是基类的final方法了(也适用于private方法,他们隐式为final)。
8.4协变返回类型:
这是jdk1.5中。
导出类的被覆盖的方法可以返回基类方法的返回类型的某种导出类型。
8.5用继承进行设计:
实际上是表明了在继承用于设计的时候,一定要慎重,:
继承要求在编译时就要知道确切的类型。
用继承表达行为间的差异,并用字段表达状态上的改变。
纯继承与扩展:
纯继承是is-a的关系:基类可以接受发送导出类的任何消息,因为二者有着完全相同的接口。我们只需要从导出类向上转型,永远不需要知道正在处理的对象的确切类型。
实际上extends用于扩展接口,这样是一种is-like-a的关系。导出类就像一个基类,除了有着同基类相同的接口外,还有自己额外方法实现的特性。
导出类中接口的扩展部分不能被基类访问。对于这种类型,在向上转型时的问题就在于,扩展部分不能被基类访问。
为了解决向上转型中,无法识别扩展部分,提出了向下转型的概念。
但是有可能出现的问题:你不知道到底要转成哪个类型。这时候就会出现运行期异常:(ClassCastException)。
实际上在java中每一次转型都会的得到检查,称之为“运行时类型识别”(RTTI)。