看了这篇文章:
https://www.ibm.com/developerworks/cn/java/j-lo-polymorph/
有一些疑问。
class Person {
public String toString(){
return "I'm a person.";
}
public void eat(){}
public void speak(){}
}
class Boy extends Person{
public String toString(){
return "I'm a boy";
}
public void speak(){}
public void fight(){}
}
class Girl extends Person{
public String toString(){
return "I'm a girl";
}
public void speak(){}
public void sing(){}
}
//最后这么用的话,
Person girl = new Girl();
girl.speak();
按照作者的说法,girl引用变量指向堆中的 Girl对象,所以运行的时候知道当前对象是Girl对象,找Girl的方法表,
找到后执行。这对于speak方法来说是行得通的。
但是如果这样呢:
girl.sing();
按照作者的说法,去Girl方法表找到sing方法,然后执行。
实际情况大家都知道有错误,编译不通过。
这中间肯定漏了点我不知道的什么?希望可以赐教。
换个方式问也就是:
当发生向上转型的时候,栈和堆中分别发生了什么?
ソース コードは次のようになります。まだ省略されている部分があります。コード全体を投稿してください。
。person girl = new Girl()
girl は入れていません。 .speak( )
これらの 2 つの文は main に配置する必要があります。クラス内で直接呼び出すと構造が間違っています
呼び出すことができるメソッドを決定するのは、変数の 宣言された型 であり、変数が指すヒープ内のオブジェクトの実際の型ではありません。
あなたにいいね!:
リーリーgirl
の宣言型はPerson
であり、Person
にはspeak
メソッドがないため、エラーが報告されます。これはコンパイラーによって報告されるコンパイル時エラーであることに注意してください。コンパイラーは、girl
がどのようなタイプで実行されるかを気にしません。の実行中、仮想マシンは当然、
girl
によって実行されるヒープ内のオブジェクトのタイプがGirl
であることを認識します。なぜコンパイラは、宣言された変数の型に基づいてメソッドを呼び出すことができるかどうかを判断するのでしょうか?理由の 1 つは、コンパイル時に、この変数が実行時にどのタイプのオブジェクトにバインドされているかがまったくわからない可能性があることです。例:
リーリーこの例では、
p
は実行時までバインドされているオブジェクトの真の型を判断できません。被験者の質問には、ポリモーフィズムの概念が含まれています。件名の例を使って説明しましょう:
サブジェクトによって定義された 3 つのクラス
リーリーPerson
、Girl
、Boy
が使用されると仮定します。いつオブジェクト
ps
を定義すると、コンパイル時の型はPerson
になりますが、実際の実行時の型はGirl
になります。
リーリーps
オブジェクトを使用する場合、プログラムはそれがPerson
であることのみを認識し、Person
にはeat
とspeak
の 2 つのメソッドしかありません。そのため、オブジェクトのメンバーを呼び出すときに、次のことが可能です。eat
とspeak
の 2 つのメソッドのみを呼び出します。プログラムはps
オブジェクトの実際の型がGirl
であることを認識していないため、Girl
の一意のsing
メソッドを呼び出すことはできません。つまり:では、プログラムは
ps
オブジェクトの実際の動的型がGirl
であることを知らないのに、なぜps.speak();
はGirl
の実装を呼び出すことができるのでしょうか?これがポリモーフィズムの機能です。サブクラスを指す親クラスのポインタ/参照の場合、親クラスのメソッドがサブクラスでオーバーライドされている場合、このメソッドが親クラスのポインタ/参照を通じて呼び出されると、コンパイラは親クラスのポインタ/参照を追加します。クラスメソッドの呼び出しは、コンパイル中にサブクラスに動的にバインドされます。サブクラスによってオーバーライドされていないメソッドは、親クラスのメソッドに静的にバインドされます。
これは、抽象的な観点から理解されます。下位レベルの実装メソッドは、主題が提供する記事でより明確に説明されている特定の実装を参照する必要があります。
スタックは person、ヒープは girl、そして person クラスは sing メソッドへの参照を持ちません。