50

以下に定義されているインターフェイスがあるとします。

public interface IFunctionality
{
    void Method();       
}

以下に示すように、抽象クラスにこのインターフェイスを実装します。

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

繰り返しますが、以下のように抽象クラスから継承する具象クラスがあります。

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

今、私は次のコードを持っています、

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

このようなものを実行した後に得られる出力は次のとおりです。

Concrete stuff
Abstract stuff
Abstract stuff

しかし、私がここで行っているのは、タイプおよびConcreteFunctionalityの変数への参照を割り当てているため、3 つのケースすべてで出力が「具体的なもの」になることを期待していたことです。AbstractFunctionalityIFunctionality

内部で起こっていること。明確にしてください。

4

3 に答える 3

73

ここ:

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

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

インターフェイスを再実装すると、次のようになります。

public class ConcreteFunctionality : AbstractFunctionality, IFunctionality

...その後、インターフェイス マッピングは in のメソッドを参照し、インターフェイスを介した呼び出し(つまり、3 回目ConcreteFunctionalityの呼び出し) に期待する動作を取得しますが、2 回目の呼び出しではまだ実装を取得します。AbstractFunctionality

一般に、メソッドをAbstractFunctionality仮想で作成し、ConcreteFunctionality. そうすればConcreteFunctionality、すべての場合に実装が使用されます。

于 2013-01-25T07:05:26.033 に答える
30

クラスを次のように定義する必要があります。

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");
    }
}

ConreteFunctionality で Method() をオーバーライドしていないため、ここでは動的ポリモーフィズムを適用できないため、ランタイム環境は AbstractFunctionality オブジェクトに関連付けられた Method() を実行します。子クラスにオーバーライドされたメソッドを実行するための実行環境を導入virtual・作成します。override

于 2013-01-25T07:05:04.743 に答える
14

キーワードがvirtualありません。overrideこれがないと、仮想機能を取得できません。

MethodAbstractFunctionality を としてvirtualマークし、MethodConreteFunctionalityとしてマークできますoverride。mihirj が示したように。

同様の問題は、 C# インターフェイス メソッドが抽象または仮想として宣言されていないのはなぜですか?で取り組まれています。

于 2013-01-25T07:04:10.110 に答える