2013-01-25 20 views
50

下に定義されるようなIインターフェイスを持っている場合としますC#インタフェースの継承

public interface IFunctionality 
{ 
    void Method();  
} 

及び以下に示すように、私は抽象クラスは、このインタフェースを実装する:再び

public abstract class AbstractFunctionality: IFunctionality 
{ 
    public void Method() 
    { 
     Console.WriteLine("Abstract stuff" + "\n"); 
    }  
} 

Iが持っています抽象クラスから継承する具体的なクラス:

public class ConcreteFunctionality: AbstractFunctionality 
{ 
    public void Method() 
    { 
     Console.WriteLine("Concrete stuff" + "\n"); 
    } 
} 

私は以下の共同de、

ConcreteFunctionality mostDerived = new ConcreteFunctionality(); 
AbstractFunctionality baseInst = mostDerived; 
IFunctionality interfaceInst = mostDerived; 
mostDerived.Method(); 
baseInst.Method(); 
interfaceInst.Method(); 

このアイテムの実行後に出力されるのは次のとおりです。

Concrete stuff 
Abstract stuff 
Abstract stuff 

しかし、私はタイプAbstractFunctionalityIFunctionalityの変数へConcreteFunctionalityの参照を割り当てている私は、ここでやっているように、すべての3例では「コンクリートスタッフ」に出力を期待されているかどうか。

内部的に何が起こっていますか。親切に明確にする。

+2

これは何かを明らかにするかもしれません:http://stackoverflow.com/questions/392721/difference-between-shadowing-and-overriding-in-c – Stormenet

+0

"隠されています、上書きされません" - 覚えておくべき良いマントラ。 (しかし、あなたのコンパイラはこれを言及しているはずです;あなたの警告はフィルタにかけられていますか?) – kmote

答えて

74

public class ConreteFunctionality:AbstractFunctionality 
{ 
    public void Method() 
    { 
     Console.WriteLine("Concrete stuff" + "\n"); 
    } 
} 

...あなたは既存メソッドをオーバーライドしていません。 新しいメソッドを作成しています。は、の既存のものを隠しています。インターフェイスがAbstractFunctionalityに実装されているため、インターフェイスマッピングテーブルがそのクラスのメソッドを参照するようになっています(この動作が本当に必要な場合は、new修飾子を使用することを推奨する警告も必要です)。今

あなたがインターフェイスを再実装場合:

public class ConcreteFunctionality : AbstractFunctionality, IFunctionality 

...その後のインターフェイスマッピングはConcreteFunctionality方法を参照すると、あなたがインタフェースを介して通話に期待する行動を取得します(すなわち3回目の呼び出し)、2回目の呼び出しではまだAbstractFunctionalityに実装されています。

AbstractFunctionalityバーチャルでメソッドを作成し、それをConcreteFunctionalityにオーバーライドするのは、一般的にはより洗練され、より健全な状態に保たれます。そうすれば、すべてのケースでConcreteFunctionalityの実装が使用されます。

+1

これは、2番目の呼び出しが依然として抽象実装を介しているため、動作を期待できません。 –

+0

@ジョンハンナ:2番目の呼び出しでも*具体的なバージョンが使用されることに気付きませんでした。編集します。 –

14

virtualoverrideのキーワードがありません。これがなければ、仮想機能は得られません。

あなたはvirtualとしてAbstractFunctionalityでMethodをマークし、overrideとしてConreteFunctionalityMethodをマークすることができます。 mihirjが示したように。取り組む

同様の問題 - あなたのようにクラスを定義する必要がWhy are C# interface methods not declared abstract or virtual?

+1

+1は興味深いリンクです。 – phoog

30

:ConreteFunctionalityであなたがメソッドを(オーバーライドしていないとして

public abstract class AbstractFunctionality:IFunctionality 
{ 
    public virtual void Method() 
    { 
     Console.WriteLine("Abstract stuff" + "\n"); 
    }  
} 

public class ConreteFunctionality:AbstractFunctionality 
{ 
    public override void Method() 
    { 
     Console.WriteLine("Concrete stuff" + "\n"); 
    } 
} 

)、ランタイム環境は、(メソッドを実行)AbstractFunctionalityに関連付けられていますここで動的多型を適用することはできません。 virtualoverrideを導入すると、子クラスでオーバーライドされたメソッドを実行するための実行時環境が作成されます。ここで

+2

ニースの答え; OPのオリジナルコードを記述する「隠蔽」という用語を導入し、「新しい」キーワードなしでメソッドを隠すとコンパイラの警告が発生することに注意してください。 – phoog