web-dev-qa-db-ja.com

この多形C#コードはなぜそれが何をしているのかを印刷するのですか?

私は最近、Polymorphism _ Inheritance OOP - C#)を理解するのを助けるための一種のパズルとして次のコードを与えられました。

// No compiling!
public class A
{
     public virtual string GetName()
     {
          return "A";
     }
 }

 public class B:A
 {
     public override string GetName()
     {
         return "B";
     }
 }

 public class C:B
 {
     public new string GetName()
     {
         return "C";
     }
 }

 void Main()
 {
     A instance = new C();
     Console.WriteLine(instance.GetName());
 }
 // No compiling!
 _

今、パズルを提示した他の開発者と長い間ロングチャットの後、私はその出力が何であるかを知っていますが、私はあなたのためにそれを台無しにしていません。私が本当に唯一の問題は私たちがその出力に着く方法、コードの踏み込み、何を継承するのかなどです。

Cが定義されているクラスのように返されると思いました。その後、CはBを継承するため、Bが返されるかどうかに関して頭を通り抜けましたが、BAを継承しています!)。).


質問:

最終的に画面に表示されている、出力の取得の中に多型と継承がどのようにしてそれらの部分をどのように再生するかを誰でも説明できますか?

67
Daniel May

簡単、継承木を念頭に置いておく必要があります。

コードでは、 'a'型のクラスへの参照を保持します。これは 'c'型のインスタンスによってインスタンス化されます。さて、仮想 'getname()'メソッドの正確なメソッドアドレスを解決するために、コンパイラは継承階層を上回り、最新のオーバーライド( 'virtual'のみがオーバーライドであることに注意してください) 'new'は完全に異なるものです...)。

それが何が起こるのかです。タイプ 'C'からの新しいキーワードは、 'c'とコンパイラのインスタンスで呼び出すのであれば役割を果たすでしょう。その後、すべての可能な継承関係を完全に無効にするでしょう。厳密に話されている、これは多型を使ってすべては何も関係ありません - 仮想メソッドまたは非仮想メソッドをマスクするかどうかを 'new'キーワードで誤って違いがないことがわかります...

クラス 'C'の「新しい」とは、この(正確な)タイプのインスタンスで 'getname()'を呼び出すと、すべてを忘れてこのメソッドを使用してください。それとは反対に 'Virtual'を意味します。この名前のメソッドを見つけるまで、呼び出し中のインスタンスの正確なタイプが何であるかに関係なく、継承ツリーを上に移動します。

3
Thomas Weller