2012-04-18 18 views
4

私は、ライブラリを書いていますし、私はインターフェイス抽象クラスのない実装のインターフェイスですか?

public interface ISkeleton 
{ 
    IEnumerable<IBone> Bones { get; } 
    void Attach(IBone bone); 
    void Detach(IBone bone); 
} 

(アタッチを持つようにしたい)とデタッチ()の実装は、実際には、すべてのISkeletonで同じである必要があります。したがって、それは本質的に可能性があります:

public abstract class Skeleton 
{ 
    public IEnumerable<IBone> Bones { get { return _mBones; } } 

    public List<IBone> _mBones = new List<IBone>(); 

    public void Attach(IBone bone) 
    { 
     bone.Transformation.ToLocal(this); 
     _mBones.add(); 
    } 

    public void Detach(IBone bone) 
    { 
     bone.Transformation.ToWorld(this); 
     _mBones.Remove(bone); 
    } 
} 

しかし、C#では多重継承ができません。だから、さまざまな問題の中で、ユーザーはスケルトンを実装するたびにスケルトンから継承することを覚えておく必要があります。

私は拡張メソッドに

public static class Skeleton 
{ 
    public static void Attach(this ISkeleton skeleton, IBone bone) 
    { 
     bone.Transformation.ToLocal(skeleton); 
     skeleton.Bones.add(bone); 
    } 

    public static void Detach(this ISkeleton skeleton, IBone bone) 
    { 
     bone.Transformation.ToWorld(this); 
     skeleton.Bones.Remove(bone); 
    } 
} 

を使用することができます。しかし、私はそれが共変ではなく、ユーザーが(アタッチをバイパスすることができますので、私は、したくない

public interface ISkeleton 
{ 
    ICollection<IBone> Bones { get; } 
} 

を持っている必要があります)とデタッチ

()メソッドを使用します。

質問:私は抽象スケルトンクラスを実際に使用する必要がありますか、または何かトリックやメソッドがありますか?

+0

トピック:「SkeletonBase」という名前を付けることをおすすめしますが、それは主観的な判断です。 – abatishchev

+0

なぜそれが 'IEnumerable'である必要がありますか? –

+0

あなたのSceletonの実装が同じであれば、最初になぜインターフェイスが必要か疑問に思っていますか?私は抽象的なSceletonBaseを使うでしょう – Reniuz

答えて

3

私は骨を特別なタイプにしてIEnumerable<T>を実装します。そうすれば、それは単一責任の原則に違反しません。

public interface ISkeleton 
{ 
    AttachableEnumerable<IBone> Bones { get; } 
} 

public class AttachableEnumerable<T> : IEnumerable<T> 
{ 
    // implementation needed. 
    void Attach(T item); 
    void Detach(T item); 
} 
+0

はい、これは完全に機能します。だから私はこのパターンを見ることができませんでした。 – Jake

5

インターフェイスにAttachDetachのメソッドを公開する必要がある場合は、インターフェイスを実装するすべてのオブジェクトが独自のスタイルで実装できるため、意図した実装をバイパスする方法が常にあります。

あなたは、このように、彼らは同様ISkeletonを実装し、抽象クラスSkeletonはスケルトンがSkeletonから継承されますISkeletonとすべてのクラスを実装させることができます。

public interface ISkeleton { ... } 

public abstract class Skeleton : ISkeleton { ... } // implement attach and detach 

public class SampleSkeleton : Skeleton { ... } 

あなたがISkeletonとしてあなたSampleSkeletonを使用することができますこの方法、あなたは限り、あなたはsealedとしてSkeletonから継承し、メソッドをマークするなど、これらの機能を実装する必要はありません限り、彼らがそうであるように(それらを上書きすることはできません。インスタンスメソッド)。

サイドノードの場合:抽象クラスの末尾にBaseという名前を付けるか、何らかの方法で基本クラスにマークを付けます(ただし、これは必ずあなた次第です)。

+0

この場合、 'ISkeleton'は必要ありません。 – Oded

+0

もちろん、あなたは正しいですか?しかし抽象クラス 'Skeleton'(またはそれを継承するクラス)が(他のインターフェースを実装するための)他のパブリックメソッドを提供する場合、アクセスを制御するインターフェースを使用する必要があります。 – Matten

+0

だから私の実際の質問については、私のポストの最後に記載されて、あなたは抽象クラスが行く方法だと言いますか? – Jake

1

あなたがISkeleton行動をラップしたい場合は、いつでも代わりに行動を継承する複合オブジェクト作ることができます:

public class Body : ISkeleton 
{ 
    private SkeletonImpl _skeleton = new SkeletonImpl; 

    public IEnumerable<IBone> Bones { get { return _skeleton.Bones; } } 

    public void Attach(IBone bone) 
    { 
     _skeleton.Attach(bone); 
    } 

    public void Detach(IBone bone) 
    { 
     _skeleton.Detach(bone); 
    } 
} 
0

あなたは「アタッチ」を実装するラッパークラスを作成することができます「Detach」メソッドを呼び出して、この機能をインターフェイスに挿入します。

関連する問題