java继承中,为什么向上转型后无法运行子类中特有的方法?
怪我咯
怪我咯 2017-04-17 17:19:39
0
4
471

看了这篇文章:
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方法,然后执行。
实际情况大家都知道有错误,编译不通过。
这中间肯定漏了点我不知道的什么?希望可以赐教。
换个方式问也就是:
当发生向上转型的时候,栈和堆中分别发生了什么?

怪我咯
怪我咯

走同样的路,发现不同的人生

全員に返信(4)
PHPzhong

ソース コードは次のようになります。まだ省略されている部分があります。コード全体を投稿してください。
person girl = new Girl()
girl は入れていません。 .speak( )
これらの 2 つの文は main に配置する必要があります。クラス内で直接呼び出すと構造が間違っています

いいねを押す +0
黄舟

呼び出すことができるメソッドを決定するのは、変数の 宣言された型 であり、変数が指すヒープ内のオブジェクトの実際の型ではありません。

あなたにいいね!:

リーリー

girl の宣言型は Person であり、Person には speak メソッドがないため、エラーが報告されます。これはコンパイラーによって報告されるコンパイル時エラーであることに注意してください。コンパイラーは、girl がどのようなタイプで実行されるかを気にしません。

の実行中、仮想マシンは当然、girl によって実行されるヒープ内のオブジェクトのタイプが Girl であることを認識します。

なぜコンパイラは、宣言された変数の型に基づいてメソッドを呼び出すことができるかどうかを判断するのでしょうか?理由の 1 つは、コンパイル時に、この変数が実行時にどのタイプのオブジェクトにバインドされているかがまったくわからない可能性があることです。例:

リーリー

この例では、p は実行時までバインドされているオブジェクトの真の型を判断できません。

いいねを押す +0
左手右手慢动作

被験者の質問には、ポリモーフィズムの概念が含まれています。件名の例を使って説明しましょう:

サブジェクトによって定義された 3 つのクラス PersonGirlBoy が使用されると仮定します。いつ

リーリー

オブジェクト ps を定義すると、コンパイル時の型は Person になりますが、実際の実行時の型は Girl になります。

ps オブジェクトを使用する場合、プログラムはそれが Person であることのみを認識し、Person には eatspeak の 2 つのメソッドしかありません。そのため、オブジェクトのメンバーを呼び出すときに、次のことが可能です。 eatspeak の 2 つのメソッドのみを呼び出します。プログラムは ps オブジェクトの実際の型が Girl であることを認識していないため、Girl の一意の sing メソッドを呼び出すことはできません。つまり:

リーリー

では、プログラムは ps オブジェクトの実際の動的型が Girl であることを知らないのに、なぜ ps.speak();Girl の実装を呼び出すことができるのでしょうか?これがポリモーフィズムの機能です。

サブクラスを指す親クラスのポインタ/参照の場合、親クラスのメソッドがサブクラスでオーバーライドされている場合、このメソッドが親クラスのポインタ/参照を通じて呼び出されると、コンパイラは親クラスのポインタ/参照を追加します。クラスメソッドの呼び出しは、コンパイル中にサブクラスに動的にバインドされます。サブクラスによってオーバーライドされていないメソッドは、親クラスのメソッドに静的にバインドされます。

これは、抽象的な観点から理解されます。下位レベルの実装メソッドは、主題が提供する記事でより明確に説明されている特定の実装を参照する必要があります。

いいねを押す +0
大家讲道理

スタックは person、ヒープは girl、そして person クラスは sing メソッドへの参照を持ちません。

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!