Chapter 8 多态
首先Music.tune()方法接受一个Instrument引用并调用这个引用的play()方法,当传入一个Wind时,Wind是Instrument(有一个play方法)的一个导出类,会动态的调用Wind中的play()方法。
能够传入Wind是因为使用了向上转型,但是向上转型会让人觉得没有使用到它本身的类型(play方法中的传入参数被没有申明有Wind类型的参数)。那么如果不想忘记它本身的类型,我们就需要创建这样一个play(wind w)方法,照这个思路的话,当我们引入更多的导出类,那是不是也必须在基类中添加相当多的play()方法,而且,若是增加的play()很多,一时忘记了某个导出类的方法,那关于类型的处理是不是变得难以操纵?
这正是多态的精髓所在,我们只和基类打交道,而不去管导出类的存在。
而这也带来一个关键性的问题,我们的编译器又是怎样知道Instrument引用所指向的是哪个对象呢?答案是动态绑定。
绑定是指将一个方法调用和方法主体关联起来称为绑定。当编译器只有一个Instrument引用时,它无法知道调用哪个方法,而解决的办法就是后期绑定----在程序运行时根据对象的类型进行绑定。这种后期绑定需要某种机制能够确定在运行时判断对象的类型,从而调用恰当的方法。 也就是说编译器不知道对象的类型,但是方法调用机制能找到正确的方法体并加以调用。
Java中除了static和final方法其它所有方法都是后期绑定。
为什么将一个方法申明为final呢:防止他人覆盖方法,或者说关闭动态绑定。
当我们扩展导出类的方法时,并不会破坏原有的方法调用,tune()方法完全可以忽略周围代码发生的全部变化,我们所做的代码修改不会对其它不应受影响的部分产生破坏。将改变的事物与未改变的事务相分离。
缺陷:覆盖私有方法 只有非private()方法才可以被覆盖
缺陷:域和静态方法 只有普通的方法调用可以是多态的,如何域的访问都是由编译器解析而不是多态的。如果某个方法是静态的,它的行为就不具有多态性。静态方法是与类而不是单个对象相关联的。
构造器内部的多态方法的行为
一个动态绑定的方法调用却会向外深入到继承层次结构内部,它可以调用导出类中的方法。如果我们是在构造器内部这样子做就可能会调用某个方法,而这个方法所操纵的成员可能还未初始化。
协变返回类型
在导出类的被覆盖的方法可以返回基类方法的返回类型的某种导出类。
用继承表达行为间的差异,用字段来表达状态上的变化。
向下转型与运行时类型识别
运行时类型识别:确保向下转型的正确性。
网友评论