10

まず、私はC#にかなり慣れていません。次のコードのように、インターフェイスにメンバー関数を宣言させたいと思います

interface IMyInterface {
    void MyAction() {
        // do stuff depending on the output of function()
    }
    void Function();
}

hereFunctionは純粋な仮想であり、 の子によって実装される必要がありIMyInterfaceます。インターフェイスの代わりに抽象クラスを使用できましたが、他のクラスから継承できませんでした...たとえばMyAction、ディレクトリでファイルを再帰的に検索し、Function見つかったファイルに適用して、例を明確にします。

インターフェイスがクラスを実装できないという制約を克服するために設計を変更するにはどうすればよいですか?

編集:C++では、テンプレートをそのまま使用します

template<class A>
static void MyAction(const A& a) {
    // do stuff depending on the output of A::Function()
};

class MyClass {
    void Function();
};

C# のインターフェイスを使用してこれを行うエレガントな方法があるかどうか疑問に思っていました。

4

9 に答える 9

11

C# では、多重継承はありません。この制限は、compositionを使用して回避できます。

次のようにインターフェイスを定義します (Functionここで定義する必要はありません)。

public interface IMyInterface
{
    void MyAction();
}

抽象で抽象クラスを宣言し、Functionこのインターフェースを実装します。

public abstract class MyInterfaceBase : IMyInterface
{
    public void MyAction()
    {
        // Do stuff depending on the output of Function().
        Function();
    }

    protected abstract void Function();
}

この抽象クラスから具体的な実装を派生させることができます。これはまだ「最終」クラスではありませんが、作成に使用されます。

public class ConcreteMyInterface : MyInterfaceBase
{
    protected override void Function()
    {
        Console.WriteLine("hello");
    }
}

それでは、「最終」の合成クラスに進みましょう。の機能を統合することによって派生しSomeBaseClass、実装されます。IMyInterfaceConcreteMyInterface

public class SomeBaseClass
{
}

public class MyComposedClass : SomeBaseClass, IMyInterface
{
    private readonly IMyInterface _myInterface = new ConcreteMyInterface();

    public void MyAction()
    {
        _myInterface.MyAction();
    }
}

アップデート

C# では、ローカル クラスを宣言できます。これは、構成クラス内ですべてを派生させることができるため、多重継承にさらに近づきます。

public class MyComposedClass : SomeBaseClass, IMyInterface
{
    private readonly IMyInterface _myInterface = new ConcreteMyInterface();

    public void MyAction()
    {
        _myInterface.MyAction();
    }

    private class ConcreteMyInterface : MyInterfaceBase
    {
        protected override void Function()
        {
            Console.WriteLine("hello");
        }
    }
}
于 2013-01-24T22:13:58.227 に答える
11

これを直接処理する唯一の方法は、抽象クラスを使用することです。インターフェイスにはいかなる形式の「ロジック」も含めることができず、単なる契約であるためです。

ただし、1 つの代替方法は、インターフェイスと静的クラスを作成することです。次に、インターフェイスを使用して拡張メソッドにロジックを配置できます。

public interface IMyInterface {
    void Function();
}

public static class MyInterfaceExtensions {
    public static void MyAction(this IMyInterface object)
    {
       // use object.Function() as needed
    }
}

ここでの主な欠点は、保守性を低下させる型の増加と、検出可能性の欠如です。

于 2013-01-24T21:27:49.283 に答える
7

拡張メソッドMyActionとして定義できます:

public interface IMyInterface
{
   void Function();
}

public static class MyInterfaceExtensions
{
    public static void MyAction(this IMyInterface obj)
    {
        obj.Function();
    }
}

例:

public class HelloWorld : IMyInterface
{
    public void Function()
    {
        Console.WriteLine("Hello World");
    }

    public static void Main(string[] args)
    {
        new HelloWorld().MyAction();
    }
} 

出力:

こんにちは世界
于 2013-01-24T21:28:49.480 に答える
2

インターフェイスは、単なるコントラクトである動作を実装できません。コントラクトを定義する際に何らかのロジックを実装したい場合は、抽象クラスを使用できます。

于 2013-01-24T21:25:52.743 に答える
2

その目的のために 。抽象クラスを定義する必要があります。デフォルトの実装を提供することも、実装を派生クラスに任せることもできます。

派生クラスが何かをオーバーライドしたい場合は、いつでもそれを行うことができます。これにより、オーバーライドしたい変更とともに base を使用する柔軟性が得られます。

于 2013-01-24T21:37:19.573 に答える
1

関数のインターフェイス (署名と戻り値の型) をインターフェイスで宣言します。次に、そのインターフェイスを実装するように定義された抽象クラスを作成し、抽象クラスに基本的な既定の実装を実装します。次に、抽象クラスから継承する他の具象クラスを作成しますが、必要に応じて、抽象クラスの基本実装を別の実装でオーバーライドします。

于 2013-01-24T21:30:10.207 に答える
1

この種の問題は、外部の振る舞いを分離することによって克服するのが最善かもしれません。MyActionこの場合、内部実装から。MyFunction.

ここでのポイントは、このクラスと他のクラスの間のインターフェイス/コントラクトの一部であるべきものと、そのコントラクトの実装の一部であるべきものを理解することです。

ここで、このオブジェクトとその消費者の間の契約が定義されます。

interface IMyInterface
{
    void MyAction();
}

現在、このインターフェイスを実装し、特定の動作を強制する基本クラス。

abstract class BaseClass : IMyInterface
{
    public void MyAction()
    {
        // do some commmon action

        // call derived implementation to deal with the outcome
    }

    protected abstract void MyFunction();
}

最後に、特定の方法で MyFunction の結果を処理する具体的な実装です。

class ConcreteClass : BaseClass
{
    protected override void MyFunction()
    {
         // concrete implementation here
    }
}
于 2013-01-24T21:35:43.887 に答える
0

インターフェイスはコントラクトであり、実装を含めることはできません。

上記のあなたの声明から:

インターフェイスの代わりに抽象クラスを使用できましたが、他のクラスから継承できませんでした

「なぜ C# は多重継承をサポートしないのか」という質問に答えていると思います。

これは、 C# のシミュレートされた多重継承に関する CodeProject の記事です。C# の単純な継承モデルを回避するには、このパターンに従う必要があります。

于 2013-01-24T21:30:56.753 に答える