コンパイル時に静的バインディングが実行され、実行時に動的バインディングが発生するという原則があります。私はいくつかの関連する質問を読んだ。私はそれらの多くの思考の電車に従うことができるが、私は台無しにし、それは以下のような具体的な質問を私に来るとき、再び私のロジックを失った:Java動的バインディングとメソッドオーバーライドプロセス
class Cake {
public void taste (Cake c) {
System.out.println("In taste of Cake class");
}
}
class ChocolateCake extends Cake {
public void taste(Cake c) {
System.out.println("In taste (Cake version) of ChocolateCake class");
}
public void taste(ChocolateCake cc) {
System.out.println("In taste (ChocolateCake version) of ChocolateCake class");
}
}
class BirthdayCake extends ChocolateCake {
public void taste(Cake c) {
System.out.println("In taste (Cake version) of BirthdayCake class");
}
public void taste (ChocolateCake cc) {
System.out.println("In taste (ChocolateCake version) of BirthdayCake class");
}
public void taste(BirthdayCake bc) {
System.out.println("In taste (BirthdayCake version) of BirthdayCake class");
}
}
次のオブジェクトが作成されています:
Cake c1 = new Cake();
ChocolateCake cc = new ChocolateCake();
Cake c2 = new ChocolateCake();
Cake c3 = new BirthdayCake();
を
出力は以下の通りである:
c1.taste(cc);//Output: In taste of Cake class
cc.taste(cc);//Output: In taste (ChocolateCake version) of ChocolateCake class
c2.taste(cc);//Output: In taste (Cake version) of ChocolateCake class
((BirthdayCake) c3).taste(cc);//Output: In taste (ChocolateCake version) of BirthdayCake class
((BirthdayCake) c3).taste((BirthdayCake) c3);//Output: In taste (BirthdayCake version) of BirthdayCake class
基本的に、私の質問は、なぜc2.taste(cc)
クラスChocolateCake
にtaste(Cake c)
メソッドを呼び出していますか? c2
の静的な型がCake
のメソッドが呼び出されることがつもりであると判断Cake
です:
は、ここに私の考えです。実行時になると、動的タイプのc2、つまりChocolateCake
が、ChocolateCake
でメソッドを決定し、ケーキが呼び出されます。パラメータの型はChocolateCake
と決定され、最終的にはtaste(ChocolateCake cc)
と呼ばれます。
明らかに、この考えは間違っています。そして、静的型がc2
でCake
であり、クラスCake
のメソッドが1つしかないので、メソッドのシグネチャがコンパイル時に解決されたとします。実行時には、クラスのオーバーライドメソッドを呼び出すことになります。私の混乱は、それが前のやり方ではなくこのように機能する理由です。
ChocolateCake cc = new Cake();
:
私は理解していないもう一つは、我々はそれがコンパイルエラーになるだろうとして、以下のような声明を書くことができていないということです。
しかし、ChocolateCake
のtaste(Cake c)
メソッドを呼び出す必要があるので、ChocolateCake型参照が最終的にCakeオブジェクトを渡すことが可能なのはなぜですか?
私はまだオブジェクト参照のメソッドを呼び出すプロセス全体を理解していないと思います。コンパイル時に最良のマッチング方法を決定するときと、それ以降に起こることは、実行時としましょう(このプロセスでは他の段階があるかどうかはわかりません)。
誰でもこのプロセスを説明できますか? ありがとう!
パラメータバインディングが動的ではないという問題があります。パラメータはコンパイル時に 'Cake.cake(Cake c)'にバインドされているため、実行時に 'Cake'になりますが、メソッド呼び出し(動的である)は' ChocolateCake.cake(Cake c) 'になります。 。おそらくこの質問には重複していることがあります。見つけられるかどうかを見てみましょう。 – Kayaman
ありがとうございます、あなたの答えは私の質問をほぼ解決しました。しかし、私は最後のいくつかの部分で述べたように、パラメータ渡しのものとまだ混乱しています。つまり、ChocolateCake cc = new Cake();という文は許可されないのに対し、最終的に 'Cake'オブジェクトを渡す' ChocolateCake'型参照はなぜ可能ですか? –
これは単なる基本的な継承です。すべてのケーキは「ケーキ」ですが、「ケーキ」は「チョコレートケーキ」ではありません(それは可能ですが、それは決定的ではありません)。あなたは 'Woman w = new Human();'と書くべきではありません。なぜならそれは必ずしも真実ではないからです。 – Kayaman