2016-12-13 2 views
-1

私は、インターフェースが多次元の関係を持つため、新しいサブインターフェースを作成せずに簡単にインターフェースを作成する方法を見つけようとしています。サブインターフェースや明示的なクラスを使用しないインターフェース

interface IAnimal {} 

interface ISwimmingAnimal : IAnimal {} 

interface IVertebrate : IAnimal {} 

interface IMammal : IVertebrate 
{ 
    IMammal Process(); 
} 

interface IInvertebrate : IAnimal {} 

interface IMollusc : IInvertebrate 
{ 
    IMollusc Process(object data); 
} 

したがって、いくつかの具体的なクラスは、ISwimmingAnimalInvertebrate又はISwimmingAnimalMammalとして組成物インタフェースを必要とせず

class Vertebrate : IVertebrate {} 

class SwimmingInvertebrate : ISwimmingAnimal, IInvertebrate {} 

class SwimmingMammal : ISwimmingAnimal, IMammal 
{ 
    IMammal Process(); 
} 

あろう。

すべてが順調といい、私は(私は理論的には欲しい)いくつかのcompostioned型のインスタンスが含まれていますクラス/インタフェースを使用する必要がありますまで:私はこの

interface IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate> 
    where TAnimal : IAnimal 
    where TVertebrate : TAnimal, IVertebrate 
    where TInvertebrate : TAnimal, IInvertebrate 
{ 
    IEnumerable<IAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates 
    {IAnimal, IVertebrate} Vertebrate { get; } 
    IEnumerable<{IAnimal, IInvertebrate}> Invertebrates { get; } 

    void UpdateVertebrate(TVertebrate vertebrate); 
    void UpdateInvertebrate(TInvertebrate invertebrate, int index); 
} 

class SwimmingAnimalsCollection<TAnimal, TVertebrate, TInvertebrate> : AnimalsCollection<TAnimal, TVertebrate, TInvertebrate> 
    where TAnimal : ISwimmingAnimal 
    where TVertebrate : TAnimal, IMammal 
    where TInvertebrate : TAnimal, IMollusc 
{ 
    public IEnumerable<TAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates 
    public TVertebrate Vertebrate { get; } 
    public IEnumerable<TInvertebrate> Invertebrates { get; } 

    public void UpdateVertebrate(TVertebrate vertebrate) {} 
    public void UpdateInvertebrate(TInvertebrate invertebrate, int index) {} 
} 
試してみた

interface IAnimalsCollection 
{ 
    IEnumerable<IAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates 
    {IAnimal, IVertebrate} Vertebrate { get; } 
    IEnumerable<{IAnimal, IInvertebrate}> Invertebrates { get; } 

    void UpdateVertebrate({IAnimal, IVertebrate} vertebrate); 
    void UpdateInvertebrate({IAnimal, IInvertebrate} invertebrate, int index); 
} 

class SwimmingAnimalsCollection : IAnimalsCollection 
{ 
    public IEnumerable<ISwimmingAnimal> Items { get; } //Aggregate collection of Vertebrate and Invertebrates 
    public {ISwimmingAnimal, IMammal} Vertebrate { get; } 
    public IEnumerable<{ISwimmingAnimal, IMollusc}> Invertebrates { get; } 

    public void UpdateVertebrate({ISwimmingAnimal, IMammal} vertebrate); 
    public void UpdateInvertebrate({ISwimmingAnimal, IMollusc} invertebrate, int index); 
} 

SwimmingAnimalsCollectionをインタフェースだけでインスタンス化する方法は見つけられません。これは最初に解決しようとしていた問題であったため、IMammalIMolluscが返される可能性があります異なるクラス。 実際の実装では、UnProcessedXというクラスのペアがあります。このクラスはProcessedXクラスを返します。これをさらに処理しようとすると、それ自体が戻ります。

私は

collection.UpdateVertebrate((TVertebrate)collection.Vertebrate.Process()) 

ProcessedVertebrateUnProssesedVertebrateではありませんをしたいと思っているので。

  • 私は打破し、組成のインターフェイスを作成することができ、任意の シンプルな依存性注入を殺す:

    は、私はこれを解決するためにおよそ三つの方法を参照してください。

  • 私はダミーの抽象基本クラスを作成できます( 深い継承チェーンは必要ありません)。依存性の可能性はありません 注入
  • また、 にリダイレクトされ、インプレースインターフェイスの作成が可能になるまで、魔法の杖でC#コンパイラを倒すことができました。
+1

を今すぐあなたのコレクションは次のようになります。質問。組成。継承ではありません。 https://en.wikipedia。org/wiki/Composition_over_inheritance – CodeCaster

+0

@CodeCasterそれから私は自分自身を正しく説明しているかどうかはわかりません。私はA、B、Cを行うことができるクラスを望んでいません。IABとIAC中間インターフェイスを定義せずに{IA、IB}と{IA IC}のインスタンスを保持できるクラスが必要です。 – Tory

+0

あなたの例のすべての 'IB'と' IC'は 'IA'です、なぜあなたは両方に拘束する必要がありますか? – InBetween

答えて

1

私はあなたが欲しいものを得ることができる最も近いが、以下の設定だと思う:

public interface IAnimal { } 
public interface IVertebrate<out TAnimal>: IAnimal where TAnimal : IAnimal { } 
public interface IInvertebrate<out TAnimal>: IAnimal where TAnimal : IAnimal { } 
public interface ISwimmingAnimal : IAnimal { } 
public interface ISwimmingVertebrate : IVertebrate<ISwimmingAnimal> { } 
public interface ISwimmingInvertebrate : IInvertebrate<ISwimmingAnimal> { } 

をあなたはまだインターフェイス間dependenyを作成していることがわかります。

public interface IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate> 
    where TAnimal: IAnimal 
    where TVertebrate: IVertebrate<TAnimal> 
    where TInvertebrate: IInvertebrate<TAnimal> 
{ 
    IEnumerable<IAnimal> Animals { get; } 
    IEnumerable<TVertebrate> Vertebrates { get; } 
    IEnumerable<TInvertebrate> Invertebrates { get; } 
    .... 
} 

public class AnimalsCollection<TAnimal, TVertebrate, TInvertebrate> : IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate> 
    where TAnimal : IAnimal 
    where TVertebrate : IVertebrate<TAnimal> 
    where TInvertebrate : IInvertebrate<TAnimal> 
{ 
    public AnimalsCollection(IEnumerable<TVertebrate> vertebrates, IEnumerable<TInvertebrate> invertebrates) 
    { 
     Vertebrates = vertebrates; 
     Invertebrates = invertebrates; 
    } 

    public IEnumerable<IAnimal> Animals => Vertebrates.Cast<IAnimal>().Concat(Invertebrates.Cast<IAnimal>());  
    public IEnumerable<TInvertebrate> Invertebrates { get; } 
    public IEnumerable<TVertebrate> Vertebrates { get; } 
} 

いくつかの具体的な種類::

public abstract class SwimmingAnimal: ISwimmingAnimal { } 
public class JellyFish: IInvertebrate<SwimmingAnimal> { } 
public class Fish: IVertebrate<SwimmingAnimal> { } 

そして今、あなただけのインターフェイス使用して、具体的なコレクションをインスタンス化することができます:キーワードは、あなたの中に既にある

var swimmingCollection = new AnimalsCollection<ISwimmingAnimal, IVertebrate<ISwimmingAnimal>, IInvertebrate<ISwimmingAnimal>>(Enumerable.Empty<Fish>(), Enumerable.Empty<JellyFish>()); 
+0

残念ながら、非空のコレクションでAnimalsにアクセスすると、無効なキャスト例外が発生します(タイプ 'Fish'のオブジェクトをキャストして 'ISwimmingAnimal'と入力できません)。そして私はあなたの提案されたコードと私の合併を試みてきました(ここで、TVertebrate:TAnimal、IVertebrate )。いずれにしても、これは私が避けようとしていたものです。 – Tory

+0

@Tory woops、間違いをした。 'Animals'は' IEnumerable 'を返さなければなりません。インタフェースがジェネリック型に拡張されないため、IEnumerable を返すのは意味がありません。 'IVertebrate'と' IInvertebrate'は 'IAnimal'を実装する必要があります。固定コード。 – InBetween

+0

うん、それはそれを修正しました(そして私の要求によってはまだ許されています)。そして、それは私の "合併された"バージョンに近いコードを作った - しかし、ずっとずっと簡単です。私はすでに 'IMammal :IVertebrate ここで、TAnimal:IAnimal'は' var animals = new AnimalsCollection 、IInvertebrate >(...)で動作しています。 '。 – Tory

関連する問題