6

これは、仮想メソッドを示す小さなコードです。

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

aF()がBFを出力する理由がわかりませんか?

クラスBがクラスAのF()をオーバーライドするため、DFが出力されると思いました。このメソッドは、「new」キーワードを使用してクラスCで非表示になり、クラスDで再びオーバーライドされます。したがって、最終的にDFは残ります。

しかし、それはそれをしていません。BFを印刷している理由を教えてください。

4

4 に答える 4

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

次のようになりF()ます。

  1. ファーストインclass A
  2. その後、class B
  3. その後、class C
  4. その後、class D

F()これで、、、に表示さAれます B。したがってB.F()、呼び出されます。F()は異なります(これclass Cは新しい実装であり、A / Bからオーバーライドされないため)。したがって、3番目のステップでは、cF()は見つかりません。クラス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"); }
    }
于 2012-07-06T05:36:06.137 に答える
2

ポリモーフィズムを可能にするメソッドのオーバーライドとは異なり、newキーワードを使用してメソッドを非表示にするには、名前を付けるだけです(使用newすると、何かを非表示にしているという警告が削除されることに注意してください)。

クラスCで、あなたが宣言するとき:

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

ここでは、スーパークラスとは関係のないまったく新しいメソッドを定義しています。F()これはたまたま同じ名前です。

のインスタンスがタイプまたはFの変数に割り当てられている場合、それらの変数を使用して呼び出すと、スーパークラスによって定義されたメソッドがポイントされます。ABF()

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

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

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

于 2012-07-06T05:33:24.843 に答える
1

AFはBFによってオーバーライドされます。したがって、AFが呼び出されると、BFBFは「AF」に「接続」されて実行されます。

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

CFはDFによってオーバーライドされます。それらは接続されています。CFまたはDFが呼び出されると、DFが実行されます。オブジェクトDをAまたはBのいずれかにキャストし、F()を呼び出すと、BFが呼び出されます。

これがそれをより明確にするのに役立つことを願っています。

于 2012-07-06T05:35:39.460 に答える
0

他の人がすでに指摘しているように、Cの新しいキーワードはFのオーバーロードを非表示にするため、CまたはDでFの適切なオーバーロードは見つかりません。

適切なオーバーロードを見つけるC#の詳細情報が必要な場合は、次の2つをお読みください。

Jon Skeet:C#in Depth、chapter Overloading

Visual Studio 2010:重大な変更、ここ:過負荷の解決

于 2012-07-06T05:53:24.303 に答える