1

ちょっとしたコードに出くわしましたが、なぜそれが機能するのか、なぜこのようにしたいのかよくわかりません。誰かが私のためにそれを壊すことができれば、私はそれが大好きです. 私は OOP の概念をよく理解していますが、この手法をこれまで見たことがありません。ありがとう

次に例を示します。

public interface IInterface
{
    IEnumerable<object> DoSomething();
}

public abstract class MyBase : IInterface
{
    protected MyBase()
    {
    }

    IEnumerable<object> IInterface.DoSomething()
    {
        return DoSomething();
    }

    protected virtual IEnumerable<object> DoSomething()
    {
        return new List<object>();
    }
}

public class MyClass : MyBase
{
    internal MyClass() : base() {}

    protected override IEnumerable<object> DoSomething()
    {
          return new List<object>();
    }
}
4

5 に答える 5

1

このコード行について話している場合:

IEnumerable<object> IInterface.DoSomething()

これは、明示的なインターフェイスの実装と呼ばれます。

これにより、消費者はクラスに直接アクセスするのではなく、インターフェースを介してのみこのメソッドにアクセスするようになります。

上記のメソッドはプライベートではなく、コードで明示的にパブリックとして設定されていません。実際、明示的なインターフェイスの実装では、アクセス修飾子を使用することさえできません。

このアプローチを取る理由の 1 つは、より良いコーディング プラクティスを強制することです。あなたがこのクラスの開発者であり、インターフェイス経由でのみアクセスする必要があることを知っている場合、これはそれを強制する方法です。

于 2013-03-11T16:10:46.023 に答える
0

注意すべき重要なことは、2 つのDoSomethingメソッドは互いに何の関係もないということです。たまたま同じ名前を持っているだけです。

基本的に、メソッドを公開する通常のインターフェイスを取得しただけなので、オブジェクトDoSomethingを持つ呼び出し元はそれを呼び出すことができます。IInterface次に、保護されたDoSomethingメソッドの適切な実装に呼び出しを渡します。これは、基本クラスまたは派生クラスからのものです。

このような明示的な実装では、実装ではなくコントラクトによってコーディングする必要があります。実際の保護はまったく提供されず、変数を宣言するときに間違った型を誤って使用することが難しくなります。彼らは同じように簡単にできたはずです:

public abstract class MyBase : IInterface {
    public virtual IEnumerable<object> DoSomething() {
       // blah
    }
}

public class MyClass : MyBase {
    public override IEnumerable<object> DoSomething() {
        // blah
    }
}

しかし、それはorDoSomethingとして宣言された変数を呼び出すことができます。MyClassMyBase

于 2013-03-11T16:24:43.957 に答える
0

C# では、保護された仮想メソッドを呼び出すだけのシールされたメソッドを使用してインターフェイスを明示的に実装すると、派生クラスは、インターフェイスで何をしたいかに関して大きな柔軟性を得ることができます。メソッドには他の名前を付ける必要がありますインターフェイスメソッドの名前よりも (上記の例では、おそらく DoSomething_Prot である可能性があります)。明示的なインターフェイスの実装により、派生クラスの再実装が基本クラスの実装に連鎖することは不可能になりますが、基本クラスの実装が保護された仮想メソッドまたは抽象メソッドに連鎖することだけが行われている場合は、派生クラスの必要はありません。インターフェイスを再実装するためのクラス。さらに、派生クラスが意図的に、または共分散の結果としてインターフェイスを再実装したとしても、基本クラスからの保護されたメソッドを使用して、基本クラスの実装の「内臓」を呼び出すことができます。

インターフェイスを暗黙的に実装するパブリック仮想メソッドにインターフェイス実装のすべてのコードを配置することは、明示的な実装にコードを配置するよりも優れています。これは、派生クラスのコードは通常、プライベート メンバーにチェーンできるためです。ただし、このようなアプローチでは、すべての派生クラスが同じシグネチャを持つメソッドをパブリックに実装する必要があります。いずれにせよ自然に期待されるように思えるかもしれませんが、常にそうであるとは限りません。たとえば、上記の例では、派生クラスはそのDoSomethingメソッドが 以外の型を返すようにしたい場合がありますIEnumerable<object>(たとえば、 を返す可能性がありますIList<Kangaroo>)。インターフェイスを実装するメソッドは正確な型を返す必要がありIList<Kangaroo>ますが、派生型を扱っていることを知っているコードは、戻り値の型を型として使用できます。IList<Kangaroo>タイプキャストなし。メソッドの実際のコードが というメソッドにある場合DoSomething_Prot()、派生クラスDoSomething_Protnew public IList<Kangaroo> DoSomething(). 基本クラスのメソッドが呼び出された場合DoSomething()、派生クラスがそれをオーバーライドして、異なる戻り値の型を持つ新しいメソッドを定義する方法はありません。

于 2013-03-11T16:45:04.893 に答える
0

頭のてっぺんから、これの実用的な使用法を考えるのに苦労していますが、これが達成することの1つは、タイプMyBaseまたはそのサブクラスのオブジェクトには、publicまたはinternal目に見えるDoSomething()メソッドがないことです。

MyClass a = new MyClass();
a.DoSomething();  // Compile error

ただし、DoSomething()オブジェクトが次のように使用されている場合、メソッドは表示されますIInterface

void AMethod(IInterface i)
{
    i.DoSomething(); // compiles just fine
}

void AnotherMethod(MyBase a)
{
    AMethod(a); // as does this
}

非明示的なバージョンを作成すると、protected virtualサブクラスがメソッドの動作をオーバーライドできますDoSomething()

MyBaseこれは、 を として処理する場合は直接呼び出せないが、としてMyBase扱われている場合は使用できるメソッドを実装する方法ですIInterfaces。誰かがこれを行うのを妨げるものは何もありません:((IInterface)a).DoSomething();しかし、隠蔽はセマンティックな理由で行われているようです.

于 2013-03-11T16:14:19.680 に答える
0

これについての私の見解は、ここで説明されているテンプレート パターンの実装であるということです。通常、テンプレート パターンは戦略パターンと共に使用されます。あなたの特定の例では、のユーザーは 、具体的なサブクラスがメソッドをどのように実装したかに関係なく、メソッドをIInterface呼び出すことができました。DoSomething

この種の OO プログラミングでは、AbstractFactory など、他のかなりの数のパターンを利用して、MyBase実装する具体的なサブクラスを作成できますIInterface

于 2013-03-11T16:19:22.850 に答える