3

たとえば、C# クラスがあるとします。

class Foo : Bar, IBar, IBar2
{

}

... ここで、Bar はクラスで、IWhatever と IFine はインターフェイスです。複数のクラスで IWhatever と IFine の同様の実装を使用する予定です。このコードをカプセル化してすべてのクラスで再利用する唯一の方法は、IWhatever を継承するクラス Whatever と IFine を継承する Fine を作成することです。これらのインターフェイスを実装するクラスのメンバーにしてから、インターフェイスから実装されたメンバーでそれらのメンバーを呼び出します。

class Foo : Bar, IWhatever, IFine
{
   IWhatever mWhatever;
   IFine mFine;
   Foo()
   {
      mWhatever = new Whatever();
      mFine = new Fine();
   }
   // from IWhatever
   void Kick()
   {
      mWhatever.Kick();
   }
   // from IFine
   void Punch()
   {
      mFine.Punch();
   }
}

私はそれを正しくやっていますか?より良い方法はありますか?

4

3 に答える 3

9

継承を介して多くのクラスに同じ複数の実装を実装しようとすると、それは設計上の臭いです。C#の複数(クラス)継承の欠如は、単一責任の原則を強制するため、実際には資産であり、この点での責任ではありません。

このように考えてください。C#で利用可能な2種類の抽象化には、実際のエンティティを表す2つの補完的な形式があります。

  • 抽象クラス:「Isa」
  • インターフェース:「何かをする」または「そのような性質/行動を持っている」

これは、異なるクラスが同じインターフェースを実装している場合でも、それぞれが異なる方法で実装する可能性が高いと想定しているため、インターフェースはほとんどの場合「中空」である必要があることを意味します。

継承の使用には注意してください。GOFの賢者の知恵を覚えておいてください:

継承よりもオブジェクトコンポジションを優先します。

したがって、解決しようとしている問題に戻ると、これを行う方がよい場合があります。

public class Foo : Bar
{
   public IWhatever Whatever
   {
      get;
      private set;
   }

   public IFine Fine
   {
      get;
      private set;
   }

   public Foo(IWhatever whatever, IFine fine)
   {
      Whatever = whatever;
      Fine = fine;
   }
}

次に、IOCコンテナーを使用して、これらのインターフェースの具体的な実装を注入します。これは私の謙虚な推薦です。

于 2012-07-14T01:13:18.537 に答える
3

より一般的にすることができます:

class Foo<TWhat, TFine> : Bar, IWhatever, IFine
    where TWhat : IWhatever, new()
    where TFine : IFine, new()
{
   IWhatever mWhatever;
   IFine mFine;
   Foo()
   {
      mWhatever = new TWhat();
      mFine = new TFine();
   }
   // from IWhatever
   public void Kick()
   {
      mWhatever.Kick();
   }
   // from IFine
   public void Punch()
   {
      mFine.Punch();
   }
}

このようにして、 andだけでなく、andFooを実装する任意のクラスを使用できるようになります。IWhateverIFineWhateverFine

しかし、それをやりたいかどうかはあなた次第です。コードの正しい構造について意見を述べる前に、より具体的な情報が必要です。

于 2012-07-14T01:03:34.740 に答える
0

You could change your interfaces to become mixin-like, exposing members as extension methods to the interface:

interface MBar {} static class BarMethods {
  public static void M(this MBar self) { ... }
}

class Foo : MBar { ... }

The whole construct interface MBar {} static class BarMethods { ... } could be seen as a single "module", like module MBar { ... }. That's why I kept the formatting like that.

于 2012-07-14T01:17:49.963 に答える