2009-08-27 9 views
3
using System; 

namespace random 

{ 

    interface IHelper 
    { 
     void HelpMeNow(); 
    } 
    public class Base : IHelper 
    { 
     public void HelpMeNow() 
     { 
      Console.WriteLine("Base.HelpMeNow()"); 
     } 
    } 
    public class Derived : Base 
    { 
     public new void HelpMeNow()   ///this line 
     { 
      Console.WriteLine("Derived.HelpMeNow()"); 
     } 
    } 
    class Test 
    { 
     public static void Main() 
     { 
      Derived der = new Derived(); 
      der.HelpMeNow(); 
      IHelper helper = (IHelper)der; 
      helper.HelpMeNow(); 
      Console.ReadLine(); 
     } 
    } 
} 

コメントのある行の新しいキーワードは少し混乱します。それは基本クラスのメソッドの実装をオーバーライドすることを意味します。 overrideキーワードを使用してみませんか?Cのインターフェイスの新しい単語#

答えて

0

を、それがにそれをシャドウイングです。 Derivedオブジェクトへの参照があると、BaseHelpMeNow関数にアクセスできなくなりますとderivedObject.HelpMeNow()Derivedの実装を呼び出します。

HelpMeNowは仮想関数をオーバーライドするのと同じではありません。 DerivedオブジェクトがBaseまたはIHelperへの参照に格納されている場合は、BaseHelpMeNow()が呼び出され、Derivedの実装にはアクセスできません。

Derived derivedReference = new Derived(); 
Base baseReference = derivedReference; 
IHelper helperReference = derivedReference; 

derivedReference.HelpMeNow(); // outputs "Derived.HelpMeNow()" 
baseReference.HelpMeNow(); // outputs "Base.HelpMeNow()" 
helperReference.HelpMeNow(); // outputs "Base.HelpMeNow()" 

もちろん、上記が望ましい動作ではなく、通常はそうでない場合、2つの可能性があります。 Baseを制御する場合は、HelpMeNow()を仮想に変更し、シャドウイングする代わりにDerivedで上書きします。あなたがBaseを制御しない場合は、少なくともそのように、IHelperを再実装することで、途中でそれを修正することができます:

class Derived : Base, IHelper{ 
    public new void HelpMeNow(){Console.WriteLine("Derived.HelpMeNow()");} 

    void IHelper.HelpMeNow(){HelpMeNow();} 
} 

Derivedのこのバージョンは、あなたが満足することができます明示的なインターフェイスの実装、と呼ばれるもの使用しています実装をクラスのパブリックインターフェイスに追加せずにインターフェイスを実装する契約。この例では、すでにから継承されたDerivedのパブリックインターフェイスに実装があるため、に変更するには、IHelperを明示的に実装する必要があります。この例では、IHelper.HelpMeNowの実装をBaseの影である公開インタフェースに転送します。

だから、この変更で、baseReference.HelpMeNow()への呼び出しは、まだ「Base.HelpMeNowを()」を出力しますが、helperReference.HelpMeNow()への呼び出しがします今出力「Derived.HelpMeNow()」。 Baseの実装を仮想に変更するほど良くはありませんが、私たちが制御しないと得られるほど良いものはBaseです。

例外:それDerivedのメソッド内からアクセス可能であるが、base.HelpMeNow()のように、base.で修飾する場合にのみ。
我々はまた、我々はBaseからこの宣言を継承していても、インターフェイスクラスが実装としてIHelperを宣言する必要が注意してください。一般に

+0

うわー、どういう返事ですか。どうもありがとうございます。私が今まで想像することのできないものよりも優れている – Tom

0

インターフェイスIBASEがdoSomethingの部材を実装し、IDerivedが継承/ IBASEが実装している場合、それはIDerived.DoSomethingがIBase.DoSomethingと同義であることが期待。一般に、これは、クラスの実装者が冗長な実装を提供する必要がなくなるので、便利です。しかし、派生インタフェースが基本インタフェースのメンバと同じ名前を持つが、別個に実装する必要があるメンバを実装する必要がある場合があります。最も一般的な状況は、(1)派生したメソッドが基本型と異なる戻り型を持つ、または(2)基本インタフェースがReadOnlyおよび/またはWriteOnlyプロパティを実装しており、 typeはRead-Writeプロパティを実装する必要があります。何らかの理由で、IReadableFooインタフェースが読み取り専用プロパティFooを提供する場合、IWritableFooは書き込み専用プロパティFooを提供し、IMutableFooインタフェースは単に両方を継承するため、Fooへの参照がIReadableFoo.FooまたはIWritableFooを参照するかどうかはコンパイラが分かりません。 Foo。 IReadableFoo.Fooだけを読み込め、IWritableFoo.Fooだけを書くことはできますが、vb.netもC#も両方を処理する新しい読み書きプロパティFooを実装しない限り、オーバーロードを解決できません。

関連する問題