14

一般的なシナリオでは、多くの場合、インターフェイスまたは抽象クラスが適切な決定ですよね?

しかし、場合によっては、具象クラスの方が優れているように見えます。例えば、

public string Replace(string old, string new)

ReplaceメソッドはString具象クラスを返します。( String はインターフェイスを実装していませんが、これは単なる例です。)

私の質問は

  1. いつインターフェイスを返す必要があり、いつ具象クラスを返す必要がありますか?

  2. program to an interface, not an implementationインターフェイスを返すための一部ですか?

4

4 に答える 4

5

場合によります。

この質問が数回尋ねられたのを見てきましたが、「場合による」という答えを説明するための良い例を次に示します。

次のクラスを検討してください。

public class MyClass
{
    public static IEnumerable<int> Test()
    {
        return new List<int> { 2, 3, 4 };
    }

    public static List<int> Test2()
    {
        return new List<int> { 2, 3, 4 };
    }
}

TestIEnumerableを返し、インターフェイスTest2の具体的な実装を返します (この場合)。最良の方法は何ですか?または?IEnumerableListTestTest2

実際には、どちらも意味的に異なります。

  • Testのみを返すため、開発者が列挙型( )で返されたオブジェクトを使用するのは、メソッド コントラクトの一部であるIEnumerableことを意味します。foreach
  • Test2インスタンスを返すとList、ユーザーはListby インデックスのオブジェクトにアクセスできます。これは、返されたオブジェクトのまったく異なる使用法です。

private static void Main(string[] args)
{
    foreach (var z in MyClass.Test())
    {
        Console.WriteLine(z);
    }

    var f = MyClass.Test2()[0];

    Console.ReadKey();
}

開発者が列挙型でのみ返されたオブジェクトを使用することを期待している場合は、インターフェイスを戻り値の型として使用できます。開発者がインターフェイスの具体的な実装のメソッド/プロパティを使用することを期待している場合 (上記の例では、インデックスによるオブジェクトへのアクセス)、具体的な型を返すことができます。

また、選択の余地がない場合もあることを忘れないでください。たとえば、Silverlight バインディングに使用するパブリック コレクションを公開する場合はObservableCollection<T>、 ではなくを返す必要があります。これは、バインディング システムがクラスIEnumerable<T>のメソッド/プロパティ/動作を実際に必要とするためです (バインディングには不十分です)。働きます)。ObservableCollectionIEnumerable

避けるべきは、毎回IEnumerable<T>使用される戻り値のメソッドです。ToList()

于 2012-03-07T09:38:33.480 に答える
3

私の意見では、密結合された方法で使用されるメソッドがある場合、つまり、クラス 1 がクラス 2 でメソッド A を呼び出し、常に特定の型が必要であり、そのメソッドが呼び出されるのはそのときだけである場合、そこで議論することができます。意味がありません。この例は、メソッドがコレクションをリストとして作成し、それを IEnumerable として返す場合に、IEnumerable を返すことです。クラス 1 はそれをリストとして消費します。

ただし、データレイヤーなどのクラス間のより分離されたインターフェイスを作成する場合は、常に最小公分母 (IEnumarable など) を返し、知識のない消費者がそれをどうするかを決定できるようにすることを好みます。

于 2012-03-07T09:16:33.017 に答える
1

あなたはProgram to an interface, not an implementation間違っていると思います。プログラムからインターフェイスへの GOF が意味するものは、型のインターフェイスです。

それらは、オブジェクトのインターフェースを、外部から見えるすべてのメソッドとして定義します。したがって、この場合のインターフェイスの定義は、たとえば C# のものとは異なります。

あなたの質問に関しては、抽象クラスを返す方がおそらく良いと思います。その抽象クラスから派生したオブジェクトを返すとうまくいきますか? はいの場合は、抽象クラスを返します。そうでない場合は、より具体的にして、派生型を返します。

于 2012-03-07T09:08:15.440 に答える
0

コードのユーザーにどの程度のアクセスを許可するかによって異なります!

つまり、ユーザーに戻っList<AccountStatement>ても意味がありません。コードのユーザーがこのコレクションに新しいステートメントを追加することを望まないためです (特定のトランザクションの予約時にステートメントが作成される必要があります)。

したがって、この場合、IEnumerable<AccountStatement>読み取りアクセスのみを返すことができます。

一般に、次の理由により、メソッドからインターフェイスを返すという考えを支持します。

  • オブジェクトに外部の世界に与えるアクセスをより適切に制御できます。
  • 実装の詳細を非表示にすることができます (その場合、クラスでさえアセンブリの内部に留まることができます)。
  • これは、インターフェイス分離の原則に沿っています (適切なインターフェイスを返し、実装することによって、必要な動作のみを公開します)。

ところで、「文字列」を返す例はあまり役に立ちません。これはプリミティブ データ型 (mscorlib のネイティブ データ型を意味します) であり、このオブジェクトで非表示/表示することはあまりありません。

于 2012-03-07T10:17:07.643 に答える