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)。