0

メソッドをオーバーライドする場合、Java は動的バインディングに従います。しかし、子オブジェクトを参照している親参照変数から子のみのメソッドを呼び出すと、コンパイル エラーが発生します。
java がこの設計に従うのはなぜですか (つまり、2 番目のケースで動的バインディングがないのはなぜですか)。

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必ずしもA そうではありません B。そのため、参照B時にメソッドを呼び出すことはできませんA

于 2013-09-05T16:28:29.060 に答える
0

次のように考えてください。B が A を拡張するとき。その意味は

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

これは、B が A のものを使用するすべての特権を持っていることを意味します (A が B のサブセットになるようなものです)。

しかし、A はここで B について知りませんでした。なので、Bのものは使えません。何らかの方法で A を B のように動作させる必要がある場合 (キャストを使用)、ここではA is not B; キャストは実行時に失敗します。

Java キャスティングの詳細については、このスレッドをお読みください。

于 2013-09-05T16:40:48.833 に答える