4.多态(Thinking in java学习四)

2020-04-16  本文已影响0人  Vinson武

多态

通过分离做什么和怎么做,从另一角度将接口和实现分离开来。多态不但能够改善代码的组织结构和可读性,还能够创建可扩展的程序。

==多态存在的三个必要条件==:

转机

方法调用绑定

注意:final的使用可以有效地关闭动态绑定。

产生正确的行为

Java中的所有方法都是通过动态绑定实现多态的

可扩展性

在一个良好的OOP程序中,大多数或者所有方法都会遵循tune()的模型,而且只与基类通信。

“覆盖”私有方法

只有非private方法才可以被覆盖。导出类中,对于基类的private方法,最好采用不同的名字。即使子类存在父类private方法相同的方法也不会覆盖,而是当作两个独立的方法。

域与静态方法
域与静态方法不存在多态,即不需要动态绑定。
注意:静态方法属于类,并不是与单个对象相关联的。

构造器和多态

构造器是static方法,构造器如何在通过多态在复杂的层次结构中运作?

构造器的调用顺序

基类的构造器总是在导出类的构造过程中被调用,而且按照继承层次逐渐向上连接,以使每个基类的构造器都能得到调用。

注意:构造器有一项特殊任务:检查对象是否被正确地构造。
所以调用每个基类的构造器,才有权限和正确初始化每个基类的构造,这样才能完整且正确地构造出一个对象。

继承与清理

通过组合与继承方法来创建新类时,永远不用担心对象的清理问题,子对象通常都会留给垃圾回收器处理。若真要进行清理,则需要特意为该类写dispose()的清理方法。在覆盖清理方法时,需要先调用基类清理方法。
对象销毁顺序应该与初始化顺序相反。

构造器内部的多态方法的行为

问题:如果一个构造器的内部调用正在构造的对象的某个动态绑定方法,会发生什么?

分析:一般的方法内部,动态绑定的调用是在运行时才决定的。在基类构造器中调用导出类中覆盖基类的方法,此时会发生调用混乱。

注意:用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法。构造器中唯一能安全调用的方法是基类中的final和private方法

初始化的实际过程(完整):

协变返回类型

Java SE5中新增了协变返回类型,它表示在导出类中的被覆盖方法可以返回基类方法的返回类型的某种导出类型。
协变返回类型允许覆盖方法时,将基类方法返回类型修改为其返回类型的某种导出类型。

用继承进行设计

组合与继承设计的区别:

组合能在运行期间决定切换不同对象,获得了动态灵活性,但是我们不能在运行期间决定继承不同的对象。

设计原则:用继承表达行为间的差异,并用字段表达状态上的变化。

class Actor { public void act(){} }

class HappyActor(){ public void act(){ print("HappyActor");} }

class SadActor(){ public void act(){ print("SadActor");}}

class stage{
    private Actor actor = new HappyActor();
    public void  change(){ actor = new SadActor();}
    public void  performPlay(){ actor.act(); }
}

纯继承与扩展

采取纯粹的方式来创建继承层次结构似乎是最好的方式,即只有在基类中已经建立的方法才可以在导出类中被覆盖。
is-a 纯粹的继承,is-like-a 有着相同的基本接口,但是它还具有其他的额外方法。

向下转型与运行时类型识别

基类转导出类称为向下转型。
Java进入运行期时仍然会对类型进行检查,这种在运行期间对类型进行检查的行为称为“运行时类型识别”(RTTI)。

上一篇下一篇

猜你喜欢

热点阅读