2012-07-06 19 views
6

これは仮想メソッドを示す小さなコードです。C#仮想メソッドの下のコードを理解する必要があります

class A 
{ 
    public virtual void F() { Console.WriteLine("A.F"); } 
} 
class B: A 
{ 
    public override void F() { Console.WriteLine("B.F"); } 
} 
class C: B 
{ 
    new public virtual void F() { Console.WriteLine("C.F"); } 
} 
class D: C 
{ 
    public override void F() { Console.WriteLine("D.F"); } 
} 

class Test 
{ 
    static void Main() 
    { 
    D d = new D(); 
    A a = d; 
    B b = d;   

    a.F(); 
    b.F();   
} 
} 

このコードは、以下の出力を印刷している:

B.F 
B.F 

a.Fは()B.Fを出力しますなぜ私が理解できないのですか?

クラスBがクラスAのF()をオーバーライドしているため、このメソッドがクラスCで「新しい」キーワードを使用して隠されているため、Dクラスで再びオーバーライドされるため、DFが印刷されると考えました。とどまる。

でも、それはしていません。 B.Fをなぜ印刷しているのか教えてください。

答えて

5
A a = d; 
a.F(); 

F()は次のようになります。そして、今F()Aに記載されています

class D、およびB

  • class Cで次に次に
  • class B
  • class A

    1. まず。したがって、B.F()が呼び出されます。 class Cでは、F()は異なります(新しい実装であり、A/Bからオーバーライドしません)。したがって、3番目のステップでは、c.F()は見つかりません。クラスDでは、Cによって作成された新しい関数をオーバーライドします。したがって、それも見つかりません。

      により新しいキーワードに、結果として得られるコードは、(仮想オーバーライドに関して)以下のようなものである

      class A 
          { 
           public virtual void F() { Console.WriteLine("A.F"); } 
          } 
          class B: A 
          { 
           public override void F() { Console.WriteLine("B.F"); } 
          } 
          class C: B 
          { 
           public virtual void F1() { Console.WriteLine("C.F"); } 
          } 
          class D: C 
          { 
           public override void F1() { Console.WriteLine("D.F"); } 
          } 
      
  • +0

    ティラックと皆さん、私は今それを得ました:-) –

    2

    多態性を許可するメソッドの上書きとは異なり、newキーワードを使用してメソッドを非表示にすることは、単なる命名の問題です。newを使用すると、何かを隠しているという警告が表示されなくなります。あなたが宣言したクラスC

    、:

    new public virtual void F() { ... } 
    

    ここでは、同じ名前を持つようにたまたまスーパークラスのF()とは無関係の新しい方法を、定義しています。 Fのインスタンスがスーパークラスによって定義された方法にそれらの変数ポイントを使用してF()を呼び出し、タイプA又はBの変数に割り当てられ

    CのメソッドF()を呼び出さなかったとしたら、G()のような何か違うものを想像してみてください。次のコードはコンパイルされません。

    a.G(); 
    b.G(); 
    

    静的AまたはBとして型指定された変数であるため、コンパイラは、新たに宣言されたメソッドを参照することはできません。あなたの例では、スーパークラスが元のメソッドF()を代わりに呼び出すという点を除いて同じ状況です。

    1

    A.FはB.Fによってオーバーライドされます。したがって、A.Fが呼び出されると、B.F.Bは 'A.F'に '接続'されます。

    今、C.Fは新しいキーワードでB.Fを非表示にします。 C.FはB.F/A.Fに接続されていません。 Cを作成してF()を呼び出すと、C.F.が実行されます。 CをタイプAまたはBにキャストし、Fを呼び出すと、B.FとA.Fが接続されているので、B.Fが実行されます。

    C.FはD.F.によって上書きされます。彼らは接続されています。 C.FまたはD.Fが呼び出されると、D.F.が実行されます。今度は、オブジェクトDをAまたはBのいずれかにキャストし、F()を呼び出すと、B.Fを呼び出します。

    これが明確になることを願っています。

    関連する問題