class Bird{
public Bird(){
}
}
class Falcon extends Bird{
public Falcon(){
}
public void fly(){
System.out.println("Fly method in falcon");}
}
public class Test{
public static void main (String args[]){
Bird b=new Falcon();
b.fly(); // error on this line
}
}
上面的代码给出了编译时错误。谁能告诉我为什么?我正在使用JDK 1.8
答案 0 :(得分:4)
基本上,如果你将某些东西声明为Bird
,那么编译器的唯一内容就是"允许"要知道它具有为Bird
定义的方法。不允许知道为Bird
的任何子类声明的任何方法(除非您使用强制转换)。
假设你要说
Bird b = new Falcon();
someMethod(b);
然后,在someMethod
:
public void someMethod(Bird b) {
b.fly();
}
这与您正在做的事情基本相同。但someMethod
对b
的唯一了解是,Bird
是某种Falcon
。在那一点上,它无法告诉它是Emu
,还是像Kiwi
或someMethod
这样没有飞行方法的东西(因为可以从程序中的其他地方调用b.fly()
。
当然,程序在看到fly
时,可能会在运行时检查 这种鸟是否有Bird b = new Falcon();
b.fly();
方法,然后抛出如果它没有例外则是例外。有些语言可以做到。 Java没有。
另外,如果您认为编译器在这种情况下应该知道:
b
Falcon
是Falcon
,因为它只是将其创建为b.fly()
:它不起作用,因为它需要过于复杂的语言规则才能允许编译器看到Bird b = new Falcon();
((Falcon)b).fly();
在这种情况下始终有效,但在其他情况下不会总是有效。语言规则需要保持相当简单和一致,以确保程序适用于符合标准的任何编译器。
但是,如果使用强制转换,可以获取子类的方法:
b
这表示检查(在运行时)Falcon
是否为Falcon
。如果是,您现在可以使用为{{1}}定义的方法。如果不是,您将获得例外。