2012-01-11 10 views
5

誰かがこの2つの例の違いを説明してください。多態性/オーバーライド

クラス

protected virtual string GetData()

クラスB

private override string GetData()

そして次

クラスA 'クラスB' が 'クラスA' から継承すると仮定すると、

protected string GetData()

クラスB

private string GetData()

スーパークラスではvirtual、サブクラスではoverrideを使用する必要があると私は常に考えていましたが、キーワードとプログラムをコンパイルしてみましたが、問題はありません。もしあれば、違いは何ですか?

+0

B.GetData()の下に波打ちがありますか? View + Error Listに警告が表示されますか?あなたがやっていることを知っているときは、* new *キーワードを使用してください。 –

+1

最初の例では、Bのメソッドをプライベートにすることはできません。それはコンパイルされません。 – TrueWill

答えて

4

表示された2番目の例では、親のGetDataが表示されず、上書きされません。

例:

private class Base 
{ 
    public virtual void Test() 
    { 
     Console.WriteLine("Base"); 
    } 

    public void Test2() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

private class Derived : Base 
{ 
    public override void Test() 
    { 
     Console.WriteLine("Derived"); 
    } 

    public void Test2() 
    { 
     Console.WriteLine("Derived"); 
    } 
} 

static void Main() 
{ 
    Base b = new Base(); 
    Derived d = new Derived(); 
    Base dInB = new Derived(); 

    b.Test(); 
    d.Test(); 
    dInB.Test(); 

    b.Test2(); 
    d.Test2(); 
    dInB.Test2(); 

    Console.ReadKey(true); 
} 

それは出力:

Base // Base.Test() 
Derived // Derived.Test() 
Derived // Derived.Test() 
Base // Base.Test2() 
Derived // Derived.Test2() 
Base // You think you're calling Derived.Test2(), but you actually call Base.Test2() 

それが派生クラスでpublic new void Test2()newキーワードを使用する必要がありますので、実際にこのサンプルは、無効です。

オペレータのオーバーロードと同じように機能します。実際には何も上書きされません。正確なタイプがDerivedの場合、新しいメソッドが呼び出されます。

メンバを隠すことには本当に注意する必要があります。オーバーライド(クラス)や実装(インターフェイス)のようなものではありません。正確なタイプの場合にのみ、newメソッドが呼び出されます。それ以外の場合は、基本タイプのメソッドが呼び出されます。

+0

ありがとう、それはそれをクリアするのに役立ちました! –

+0

あなたは大歓迎です:) – Aidiakapi

3

違いは、最初の場合は上書きし、後者の場合は完全に異なる隠れていることです。

最初のケースで:第2のケースで一方

class B: A 
{ 
    void Foo() 
    { 
     B b = new B(); 
     A a = b; 

     a.GetData() //B's GetData() will be called 
     b.GetData() //B's GetData() will be called 
    } 
} 

:あなたは、単に)のGetData(のAの実装を隠している第2のケースで

class B: A 
{ 
    void Foo() 
    { 
     B b = new B(); 
     A a = b; 

     a.GetData() //A's GetData() will be called 
     b.GetData() //B's GetData() will be called 
    } 
} 

が、あなたは常にますたとえ変数がタイプBのインスタンスを参照していたとしても、A型の変数を使ってAの実装を呼び出せるようになります。これは、オーバーライドの動作とはまったく異なります。

+0

説明ありがとうございます! –

0
public class A 
{ 
    public virtual string GetData() { return "A";} 
} 

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

次のコードブロックのようなクラスを使用している場合、あなたは何を期待していますか?

 A a = new A(); 
     B b = new B(); 
     A c = new B(); 

     Console.WriteLine(a.GetData()); 
     Console.WriteLine(b.GetData()); 
     Console.WriteLine(c.GetData()); 

"A" "B" "B"が印刷されます。変数cはA型として格納されますが、メソッドを実行するときにはコードは "実際の"実装に解決されます。 (仮想関数テーブルと解決の原則については、googleを参照してください)

以下のコードのように仮想と上書きを使用しないと、 "A" "B" "A"が表示されます。

public class A 
{ 
    public string GetData() { return "A";} 
} 

public class B : A 
{ 
    public new string GetData() { return "B"; } 
}