java -----理解java的三大特性之多态

从程序的运行结果中我们发现,a.fun1()首先是运行父类Wine中的fun1().然后再运行子类JNC中的fun2()。

分析:

在这个程序中子类JNC重载了父类Wine的方法fun1(),重写fun2(),

而且重载后的fun1(String a)与 fun1()不是同一个方法,

由于父类中没有该方法,向上转型后会丢失该方法,

所以执行JNC的Wine类型引用是不能引用fun1(String a)方法。

而子类JNC重写了fun2() ,那么指向JNC的Wine引用会调用JNC中fun2()方法。

---另一个经典的例子:

 

首先我们先看一句话:

当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,

但是这个被调用的方法必须是在超类中定义过的,

也就是说被子类覆盖的方法。

这句话对多态进行了一个概括。

其实在继承链中对象方法的调用存在一个优先级:

this.show(O)、

super.show(O)、

this.show((super)O)、

super.show((super)O)。

      分析:

      从上面的程序中我们可以看出A、B、C、D存在如下关系。

首先我们分析5,

a2.show(c),a2是A类型的引用变量,所以this就代表了A,a2.show(c),它在A类中找发现没有找到,

于是到A的超类中找(super),由于A没有超类(Object除外),

所以跳到第三级,也就是this.show((super)O),

C的超类有B、A,所以(super)O为B、A,this同样是A,

这里在A中找到了show(A obj),

同时由于a2是B类的一个引用且B类重写了show(A obj),

因此最终会调用子类B类的show(A obj)方法,

结果也就是B and A。

      方法已经找到了但是我们这里还是存在一点疑问,我们还是来看这句话:

当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,

但是这个被调用的方法必须是在超类中定义过的,

也就是说被子类覆盖的方法。

这我们用一个例子来说明这句话所代表的含义:a2.show(b);

      这里a2是引用变量,为A类型,它引用的是B对象,因此按照上面那句话的意思是说有B来决定调用谁的方法,所以a2.show(b)应该要调用B中的show(B obj),产生的结果应该是“B and B”,但是为什么会与前面的运行结果产生差异呢?这里我们忽略了后面那句话“但是这儿被调用的方法必须是在超类中定义过的”,那么show(B obj)在A类中存在吗?根本就不存在!所以这句话在这里不适用?那么难道是这句话错误了?非也!其实这句话还隐含这这句话:它仍然要按照继承链中调用方法的优先级来确认。所以它才会在A类中找到show(A obj),同时由于B重写了该方法所以才会调用B类中的方法,否则就会调用A类中的方法。

      所以多态机制遵循的原则概括为:

当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,

但是这个被调用的方法必须是在超类中定义过的,

也就是说被子类覆盖的方法,

但是它仍然要根据继承链中方法调用的优先级来确认方法,

该优先级为:

this.show(O)、

super.show(O)、

this.show((super)O)、

super.show((super)O)。

 

posted @ 2017-10-17 14:44  AlamZ  阅读(274)  评论(0编辑  收藏  举报