0

我知道对于覆盖方法的情况,Java 遵循动态绑定。但是如果我们从父引用变量中调用一个子方法,它引用子对象,我们会得到编译错误。
为什么java遵循这种设计(即为什么在第二种情况下没有动态绑定)?

class A{
    public void sayHi(){ "Hi from A"; }
}


class B extends A{
    public void sayHi(){ "Hi from B"; 
    public void sayGoodBye(){ "Bye from B"; }
}


main(){
  A a = new B();

  //Works because the sayHi() method is declared in A and overridden in B. In this case
  //the B version will execute, but it can be called even if the variable is declared to
  //be type 'A' because sayHi() is part of type A's API and all subTypes will have
  //that method
  a.sayHi(); 

  //Compile error because 'a' is declared to be of type 'A' which doesn't have the
  //sayGoodBye method as part of its API
  a.sayGoodBye(); 

  // Works as long as the object pointed to by the a variable is an instanceof B. This is
  // because the cast explicitly tells the compiler it is a 'B' instance
  ((B)a).sayGoodBye();

}
4

3 回答 3

1

在方法调用的动态分派生效之前,代码必须经过编译器。当您使用类的引用调用方法时C,编译器会在该类中查找该方法的声明C。编译器只关心它是什么引用类型。它只能验证对那么多信息的方法调用。如果它在类中找不到方法,C它会给你编译器错误。

因此,对于调用:

a.sayGoodBye(); 

由于a是 class 的引用A,编译器会在 class 中寻找方法A,如果找不到,就会报错。

于 2013-09-05T16:28:26.187 回答
0

可以这样想:当 B 扩展 A 时;它的意思是

B = <All non-private stuff of A> + Its own stuff

这意味着 B 有权使用 A 的东西。(就像 A 成为 B 的子集)

但是 A 从来不知道这里的 B 以及 B 包含什么;所以,它不能使用B的东西。如果以某种方式需要强制 A 表现得像 B (我们使用强制转换)并且因为这里A is not B; 强制转换将在运行时失败。

要了解有关 Java 转换的更多信息,请阅读此线程

于 2013-09-05T16:40:48.833 回答
0

B 是一个 A,但A 不一定 B。SoB的方法不能在引用时A调用

于 2013-09-05T16:28:29.060 回答