9

依存性注入に関して明示的にインターフェイスを実装する利点はありますか?

私が理解している限り、インターフェイスは明示的または暗黙的に実装できます。

interface IFoo
{
    void Bar();
}

//implicit implementation
class Foo1 : IFoo
{
    public void Bar(){}
}

//explicit implementation
class Foo2 : IFoo
{
    void IFoo.Bar(){}
}

明示的な実装はインターフェイス メソッドを呼び出すことによってのみ呼び出すことができますが、暗黙的な実装はクラスのインスタンスで直接呼び出すことができます。

class Baz
{
    void Ba()
    {
        Foo1 foo1 = new Foo1();
        foo1.Bar();

        Foo2 foo2 = new Foo2();
        foo2.Bar();    //syntax error

        IFoo foo2_explicit = new Foo2();
        foo2_explicit.Bar();
    }
}

したがって、明示的なインターフェース実装を使用すると、具象クラスのメソッドを誤って呼び出すことはできませんが、インターフェース メソッドを呼び出す必要があります。これは、DI の目的の 1 つである密結合コードを妨げますか、それともここで間違ったツリーを吠えていますか? 結局のところ、インターフェイスの代わりに注入された具象クラスを取得するコンストラクターまたはメソッドを誤って作成することはできません。

class Baz
{
    void Ba(Foo2 foo)
    {
        foo.Bar(); //syntax error
    }

    void Bb(IFoo foo)
    {
        foo.Bar();
    }
}
4

3 に答える 3

8

通常、依存性注入の目的はデカップリングです。これは、クライアントに抽象化を注入することで実現します。

public class Baz
{
    private readonly IFoo foo;

    public Baz(IFoo foo)
    {
        this.foo = foo;
    }

    // Members using this.foo go here...
}

これにより、 がBazに依存しIFoo、具体的な実装から切り離されます。

IFoo具象クラスが暗黙的または明示的に実装されているかどうかに違いはありません。

たまに、クラスがConcrete Dependencyを持つことがありますが、これは特に正常ではありません。そしてそれが起こると、具体的な依存関係はconcreteなので、インターフェースをまったく実装しないことがよくあります。このような場合、明示的なインターフェース実装と暗黙的なインターフェース実装は関係ありません。

于 2015-07-28T11:36:11.617 に答える
1

クラスがコンテナ内にある場合は、インターフェイスを使用します。したがって、メリットはありません。

ただし、クラスを直接 (たとえばテストで) 使用する場合は、メソッドにアクセスするためにキャストする必要があり、便利ではありません。

合計: コンテナー内でクラスを使用する場合の利点は 0 で、テストの場合は不利です。

于 2015-07-28T11:35:05.010 に答える
0

私の意見では、一般に、使用するのに「十分な」タイプのオブジェクトへの参照を常に保持する必要があります。次の例を検討してください。

public interface IDo
{
    void Do();
}

public interface IWatch
{
    void Watch();
}

public class Foo : IDo, IWatch
{
    public void Dummy() { }

    public void Watch() { }

    public void Do() { }
}

その後:

//I only want to use Do()
IDo aFoo = new Foo();

//I only want to use Watch()
IWatch bFoo = new Foo();

//I want to use stuff from Foo and optionally stuff from IDo or IWatch
Foo cFoo = new Foo();

MEF や Unity などの依存性注入コンテナーを使用する場合は、インターフェイスを使用してオブジェクトをコンテナーにエクスポートし、同じインターフェイス タイプでインポートする必要があります。

これらのパターンに従っていると、明示的なインターフェイスの実装を使用するメリットはあまりありません。(また、テキスト エディターの上にある標準の Visual Studio コンボボックスで実装メソッドを見つけるのが難しくなります)

于 2015-07-28T11:40:06.640 に答える