没有抽象类的实现接口?

时间:2012-04-18 13:07:35

标签: c# .net abstract-class interface-implementation

我正在写一个库,我想要一个接口

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类,还是有任何或技巧和方法?

5 个答案:

答案 0 :(得分:5)

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

您可以让抽象类Skeleton实现ISkeleton,并且所有Skeletons类都继承自Skeleton,因此它们也会实现ISkeleton

public interface ISkeleton { ... }

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

public class SampleSkeleton : Skeleton { ... }

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

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

答案 1 :(得分: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);
}

答案 2 :(得分: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);
    }
}

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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