4

我正在写一个库,我想要一个界面

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

对于每个 ISkeleton,Attach() 和 Detach() 实现实际上应该是相同的。因此,它基本上可以是:

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# 不允许多重继承。因此,在各种问题中,用户每次想要实现 Skeleton 时都必须记住从 Skeleton 继承。

我可以使用扩展方法

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; }
}

我不想要,因为它不是协变的,用户可以绕过 Attach() 和 Detach() 方法。

问题:我必须真的使用抽象 Skeleton 类还是有任何技巧和方法?

4

5 回答 5

5

如果您需要在接口中公开AttachDetach方法,总有一种方法可以绕过您的预期实现,因为实现该接口的所有对象都可以按照自己的风格实现它们。

您可以让抽象类Skeleton实现ISkeleton,并且所有作为骨架的类都继承自Skeleton,因此它们也实现ISkeleton了。

public interface ISkeleton { ... }

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

public class SampleSkeleton : Skeleton { ... }

这样您就可以使用SampleSkeletonas ISkeleton,只要您从方法继承Skeleton并将方法标记为sealed不允许覆盖它们(只要它们是实例方法),就不必实现这些功能。

在一个侧面节点上:请务必Base在末尾命名您的抽象类或以其他方式标记基类(但这肯定取决于您)。

于 2012-04-18T13:11:55.013 回答
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);
}
于 2012-04-18T13:13:28.507 回答
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);
    }
}
于 2012-04-18T13:18:55.143 回答
0

可能您只需要在抽象 Skeleton 类上使用密封方法吗?这样他们就不能被覆盖。

http://msdn.microsoft.com/en-us/library/aa645769(v=vs.71).aspx

于 2012-04-18T13:16:10.133 回答
0

您可以创建一个实现“附加”和“分离”方法的包装类,并将此功能注入您的接口。

于 2012-04-18T13:22:59.997 回答