8

クラスの使用をそのインターフェースにロックする方法として、明示的なインターフェースを使用するための議論を見てきました。議論は、他の人にインターフェイスへのプログラミングを強制することで、クラスの分離を確実にし、テストを容易にすることができるというものです。

例:

public interface ICut
{
    void Cut();
}
public class Knife : ICut
{
    void ICut.Cut()
    {
        //Cut Something
    }
}

そして、Knife オブジェクトを使用するには:

ICut obj = new Knife();
obj.Cut();

このインターフェイス実装方法をお勧めしますか? なぜですか、そうでないのですか?

編集:また、私が明示的なインターフェースを使用していることを考えると、以下は機能しません。

Knife obj = new Knife();
obj.Cut();
4

11 に答える 11

4

GoFの第1章を引用するには:

  • 「実装ではなく、インターフェースへのプログラム」。
  • 「クラス継承よりもオブジェクト合成を優先する」.

C# には多重継承がないため、オブジェクトの構成とインターフェイスへのプログラミングが適しています。

ETA: とにかく、多重継承を使用するべきではありませんが、それはまったく別のトピックです.. :-)

ETA2: 明示的なインターフェイスについてはよくわかりません。それは建設的ではないようです。ICut としてインスタンス化されている場合にのみ Cut() できるナイフが必要なのはなぜですか?

于 2008-10-07T15:02:00.097 に答える
3

特定のメソッドへのアクセスを制限したいシナリオでのみ使用しました。

public interface IWriter
{
    void Write(string message);
}

public interface IReader
{
    string Read();
}

public class MessageLog : IReader, IWriter
{
      public string Read()
      {
           // Implementation

          return "";
      }

      void IWriter.Write(string message)
      {
           // Implementation
      }
}

public class Foo
{
    readonly MessageLog _messageLog;
    IWriter _messageWriter;

    public Foo()
    {
         _messageLog = new MessageLog();
         _messageWriter = _messageLog;
    }

    public IReader Messages
    {
        get { return _messageLog; }
    }
}

これで、Foo は _messageWriter を使用してメッセージ ログにメッセージを書き込むことができますが、クライアントは読み取りしかできません。これは、クラスが ComVisible であるシナリオで特に役立ちます。クライアントは Writer 型にキャストできず、メッセージ ログ内の情報を変更できません。

于 2008-10-07T15:21:15.953 に答える
2

これらを使用すると多態性が損なわれるため、これは悪い考えです。使用される参照のタイプによって、オブジェクトの動作が変わることはありません。疎結合を確保したい場合は、クラスを内部化し、DI テクノロジ (Spring.Net など) を使用します。

于 2008-10-24T17:57:47.727 に答える
2

はい。そして、テストのためだけではありません。一般的な動作をインターフェイス (または抽象クラス) に組み込むことは理にかなっています。そうすれば、ポリモーフィズムを利用できます。

public class Sword: ICut
{    
  void ICut.Cut()   
  {        
     //Cut Something   
  }
}

Factory は鋭利な道具のタイプを返すことができます!:

ICut obj = SharpImplementFactory();

obj.Cut();
于 2008-10-07T14:57:48.717 に答える
2

コードのユーザーに、使用させたいインターフェイスの型にオブジェクトをキャストするよう強制することには、確かな利点があることに疑いの余地はありません。

しかし、全体として、インターフェイスへのプログラミングは方法論またはプロセスの問題です。インターフェイスへのプログラミングは、単にコードをユーザーにとって煩わしくするだけでは達成されません。

于 2008-10-26T14:18:29.860 に答える
1

明示的なインターフェイス タイプを期待する呼び出し元のみを許可することで、メソッドが必要なコンテキストでのみメソッドが表示されるようになります。

ゲーム内の論理エンティティを考えてみると、エンティティの描画/ティックを担当するクラスの代わりに、ティック/ドローのコードをエンティティに含めることを決定します。

IDrawable.draw() と ITickable.tick() を実装すると、ゲームが期待するときにのみエンティティを描画/ティックできるようになります。そうしないと、これらのメソッドが表示されなくなります。

より少ないボーナスは、複数のインターフェイスを実装する場合です。明示的な実装により、2 つのインターフェイス メソッド名が衝突するケースを回避できます。

于 2008-10-24T17:43:33.123 に答える
1

インターフェイスを明示的に実装するもう 1 つのシナリオは、機能を既に実装しているが、別のメソッド名を使用している既存のクラスを処理する場合です。たとえば、Knife クラスにすでに Slice というメソッドがある場合、次の方法でインターフェイスを実装できます。

public class Knife : ICut
{
     public void Slice()
     {
          // slice something
     }

     void ICut.Cut()
     {
          Slice();
     }
}
于 2009-06-12T16:57:53.750 に答える
1

まあ、組織的な利点があります。ICuttingSurface、ICut、および関連する機能を、自己完結型でユニット テスト可能なアセンブリにカプセル化できます。ICut インターフェースの実装は簡単にモック可能であり、実際の実装ではなく ICut インターフェースのみに依存するように作成できるため、よりモジュール化されたクリーンなシステムが実現します。

また、これにより、継承がより単純化され、ポリモーフィズムをより柔軟に使用できるようになります。

于 2008-10-07T14:54:57.333 に答える
1

このメソッドでインターフェイスを使用しても、それ自体では分離されたコードにはなりません。これだけを行うと、難読化の別のレイヤーが追加されるだけであり、後でこれがさらに混乱する可能性があります。

ただし、インターフェイス ベースのプログラミングを制御の反転および依存性注入と組み合わせると、実際にどこかへ到達することになります。テスト駆動開発を行っている場合は、このタイプのセットアップでユニット テスト用のモック オブジェクトを利用することもできます。

ただし、IOC、DI、および TDD はすべてそれ自体が主要なトピックであり、これらの各主題については本全体が書かれています。うまくいけば、これがあなたが研究できることの出発点を与えるでしょう.

于 2008-10-07T14:57:57.093 に答える
0

クライアントコードがオブジェクトを使用できるという事実以外のことを気にしない場合はCut()ICut.

于 2008-10-07T14:54:35.820 に答える
0

はい。

例:

私の現在のプロジェクトでは、データ入力用のツールを構築しています。すべての (またはほぼすべての) タブで使用される特定の機能があり、すべてのデータ入力コントロールを含む単一のページ (プロジェクトは Web ベース) をコーディングしています。

このページには、ナビゲーションと、すべての一般的なアクションを操作するためのボタンがあります。

各関数のメソッドを実装するインターフェイス (IDataEntry) を定義し、そのインターフェイスを各コントロールに実装することで、aspx ページで実際のデータ入力を行うユーザー コントロールのパブリック メソッドを起動できます。

インタラクション メソッドの厳密なセット (例の「カット」メソッドなど) を定義することにより、インターフェイスを使用すると、オブジェクト (ビジネス オブジェクト、Web コントロールなど) を取得し、定義された方法で操作できます。仕方。

たとえば、ナイフ、のこぎり、ブロートーチ、モノ フィラメント ワイヤなど、任意の ICut オブジェクトに対して cut を呼び出すことができます。

テスト目的であれば、インターフェースも良いと思います。インターフェイスの期待される機能に基づいてテストを定義する場合は、説明に従ってオブジェクトを定義し、それらをテストできます。これは非常に高度なテストですが、それでも機能が保証されます。ただし、これは個々のオブジェクトメソッドの単体テストに取って代わるものではありません...「obj.Cut」が間違ったものがカットされたり、間違った場所でカットされたりした場合、それを知っても意味がありません。

于 2008-10-07T14:57:41.900 に答える