class Amphibian{ public void name() { System.out.println("两栖动物"); } public static void play(Amphibian a) { a.name(); } } public class Frog extends Amphibian{ // public void name() // { // System.out.println("青蛙"); // } // public static void play(Amphibian a) // { // a.name(); // } public static void main(String[] args) { Frog f=new Frog(); Amphibian.play(f); } }
子类中没有覆盖父类的方法时,向上转型后输出结果为 两栖动物
如果将程序中的注释部分还原,输出结果变成了 青蛙
此时的向上转型的效果并不显现,这是为什么?
而且play()方法是通过Amphibian调用的,怎么能够访问到子类的方法呢?
父类引用 指向 子类对象。也就是你所说的向上转型。有这样的规则:
(1)这个引用只能调用父类中存在的方法,而不能调用父类中不存在的方法,就算子类实现了某个特别的方法也不行。
(2)这个引用调用的方法如果被子类覆盖了,也就是重写了,那么实际执行的是子类中实现的代码。
仔细揣摩这两个规则,会发现非常的奇妙。
比如List list1 = new ArrayList(); List list2 = new LinkedList();
不管是list1还是list2,都只能使用List本身所具有的方法,但是list2就不能使用push()方法,就算LinkedList中定义了也不行。
其实第二个规则带来了一个好处,我们在使用list1和list2的时候,比如get()方法,都是调用get()方法,但是实际上具体实现是不一样的。其中一个是ArrayList实现的,另一个是LinkedList实现的。这就是多态了。
哦,谢谢你的回答
别说f是子类引用,就算f是父类引用,只要子类覆盖了父类方法,你的输出都会是青蛙
这就是为何父类提倡使用抽象类的原因,父类的作用就是抽象各种操作,成为一个模板。具体的实现,都是依赖子类来完成。
在执行时就可以动态的调用子类的方法了。