2010-12-17 8 views
11

私は、インターフェイスに関する特定のクエリを1つ持っています。デフォルトでは、インタフェースメソッドは抽象型と仮想型ですので、そのインタフェースを実装してクラス内に定義を与えると、実際にはそのメソッドをオーバーライドしますが、実装クラス内でメソッドを仮想として再度マークすると、元のインターフェイスの仮想メソッドを隠すために。私たちが基本クラスに仮想メソッドを持っていて、派生クラスがメソッドをバーチャルとして再びマークした場合、コンパイラは基本クラスメソッドを隠しているという警告を表示します。基本クラスのメソッドを隠します。インターフェイスメソッドの実装中に仮想が許可されるのはなぜですか?

public interface ITestInterface 
{ 
void virtualmethod(); // this method is by default virtual. 
} 

public class TestInterface :ITestInterface 
{ 
public virtual void virtualmethod() 
{ 
// Now compiler should consider that i am actually hiding the interface virtual method. 
} 
} 

あなたがILDASMのインターフェイスとオープンのために上記のコードをビルドする場合は、このようなコードが表示されます:インタフェースから実装されてい .method public hidebysig newslot abstract virtual instance void virtualmethod() cil managed { }//end of method ITestInterface::virtualmethod

+2

仮想の代わりに、インターフェイスのメソッドがデフォルトでは抽象であるとすると、理にかなっています。 –

+0

はい、いいですが、コンパイラが仮想メソッドにアタッチすると、メソッドを実装している間に再び仮想メソッドを実装すると、コンパイラは元の宣言を隠していると言います。 –

答えて

39

方法は、デフォルトでは仮想ないです。インタフェース定義で定義されているコントラクトの実装を提供しているだけです。メソッドをvirtualとマークすることで、派生クラスが定義されているコントラクトを引き続き尊重しながら、追加または個別の実装を提供できるようになります。

interface IAnimal 
{ 
    string Speak(); 
} 

class Dog : IAnimal 
{ 
    public string Speak() 
    { 
     return "Bark!"; 
    } 
} 

Dogクラスである契約IAnimalの実装を提供することによって、インタフェースを実装:

この例を考えます。ここには仮想メソッドはなく、オーバーライドもありません。

は今、この例を考えてみます。

interface IAnimal 
{ 
    string Speak(); 
} 

class Dog : IAnimal 
{ 
    public virtual string Speak() 
    { 
     return "Bark!"; 
    } 
} 

class GoldenRetriever : Dog 
{ 
    public override string Speak() 
    { 
     return "I am a golden retriever who says " 
        + base.Speak(); 
    } 
} 

は今Dogクラスは、派生クラスの追加や、新たな実装を提供することを可能にするvirtualするSpeakを宣言しました。 Speakメソッドへの呼び出しがまだ文字列を返すので、これはIAnimalとの契約を中断しません。

いいえ、最後の例です。インターフェイスは実装を必要とせず、契約が満たされていることのみを要求します。つまり、インタフェースは、実装クラス内に一致するシグネチャを持つメンバーが存在することのみを認識します。これは、我々はまた、この操作を行うことができることを意味します

interface IAnimal 
{ 
    string Speak(); 
} 

abstract class Dog : IAnimal 
{ 
    public abstract string Speak(); 
} 

class GoldenRetriever : Dog 
{ 
    public override string Speak() 
    { 
     return "I am a golden retriever"; 
    } 
} 

お知らせ今Dogクラスは全くSpeakのための実装を提供しないことを、まだ契約の要件を満たしています。

インターフェイスもクラスからクラスに継承されるため、上記のすべての例ではDogGoldenRetrieverの両方がIAnimalインターフェイスを実装しています。いずれのクラスもSpeakメソッドを非表示にします。両方のクラスを実装しています。


私はあなたの混乱は、仮想メソッドがクラスではなくインターフェースで定義されているという事実から来ていると思います。ここで私は上記で定義されたインタフェースのためのILは、次のとおりです。

.class private interface abstract auto ansi IAnimal 
{ 
    .method public hidebysig newslot abstract 
     virtual instance string Speak() cil managed 
    { 
    } 
} 

あなたがここにも種類がinterfaceに指定されていることに気づく必要があるvirtualなどの方法が定義されていることが正しいですが。これは純粋にマイクロソフトのC#コンパイラによって生成されたMSILの実装の詳細です。別のコンパイラでも意味的に同じ結果が得られれば、別のコードを簡単に生成できます。

ここで重要なのは、メソッドがvirtualとしてインターフェイスに宣言されていても、クラスで宣言されたvirtualメソッドと同じことを意味するものではありません。

+0

同じIDのILコードを追加したのでもう一度よく質問をチェックしてください。 –

+0

method public hidebysig newslot抽象仮想インスタンスvoid virtualmethod()cil managed {} //メソッドの終了ITestInterface :: virtualmethod –

2

インターフェイスは基本クラスではないため、実装方法はオーバーライドされません。インタフェースはメソッドを宣言するだけです。インタフェースメソッドはデフォルトでは仮想ではありません。infactインタフェースは、そのインタフェースを実装するクラスで利用可能なメソッドを宣言します。

宣言を仮想にすることはできません。

実装は、実装者のロジックに完全に依存する仮想とすることも、できないこともあります。

+0

インターフェイスは単なる仮想メソッドは、動作がクラスと同じになるようにします。 –

+1

@モート - これは完全に真実ではありません。はい、彼らはちょうど別のタイプですが、それらはすべての違いをもたらす*インタフェース*タイプです。 ILレベルでは、インターフェイスとクラスが異なります。 –

関連する問題