如何在抽象基类中部分实现契约?

时间:2010-07-22 18:39:40

标签: c# .net

我有一个如下界面

 public interface IX
    {
        void MethodA();
        void MethodB();
    }

我在MethodA和MethodB接口中有两个方法契约。我将定义将实现上述接口的类集。在这两种方法中,MethodA对于将实现该接口的所有类型都是通用的。我可以定义一个抽象类,如下所示

public abstract class XBase:IX
    {
        public void MethodA()
        { 
            // Common behaviour implementation
        }

        public abstract void MethodB();
    }

并将此类继承到需要实现上述接口的所有类型。有用。

但是在抽象类中我添加了'public abstract void MethodB();'。它看起来像重复了MethodB合约。

如果类是抽象的,为什么C#不允许部分接口实现?上面的接口只有两种方法。假设一个接口有10个方法,5个是常用功能,5个不是,我们被迫添加抽象类中不常见的5个方法?

6 个答案:

答案 0 :(得分:8)

因为C#语言规范是这样说的。第13.4.7节:

  

与非抽象类一样,抽象类必须提供类的基类列表中列出的接口的所有成员的实现。

为什么C#设计师选择指定这样的语言可能是Eric Lippert最好的答案。我个人猜测减少意外隐藏方法发生的几率,产生很难解释的错误信息。对于接口方法实现,我个人更愿意使用覆盖关键字。但他们选择不这样做。

答案 1 :(得分:1)

它不支持这一点的原因是因为你的超类不符合合同。抽象类强制实现其子类的唯一方法是定义抽象方法。

如果您不希望抽象类定义那些抽象方法,那么您必须告诉子类来实现接口。

问题必须是,为什么在你的超类上有5个抽象方法会出现问题?

答案 2 :(得分:0)

接口确实将契约要求传递给彼此,因此,只要您拥有IFooIBar : IFoo,那么从IBar继承的类必须实现这两个接口,因为IBar {{ 1}}无法实现IFoo本身的成员。为什么这种行为无法扩展到抽象基类,我不知道。我确信有充分的理由,因为汉斯发布了规范,这显然是有意的。

作为请不要在家尝试方法,你可以做类似的事情

class Derived : Base, IFoo
{
    public void MethodB()
    {
    }
}

abstract class Base
{
    public Base()
    {
        if (!(this is IFoo))
            throw new InvalidOperationException("must implement IFoo");
    }

    public void MethodA() { }
}

interface IFoo
{
    void MethodA();
    void MethodB();
}

哪个抽象基础实现了它想要的方法,然后强制派生类通过强制派生类实现接口来实现其余的。然后,派生类将负责实现基类中尚不存在的方法。这种方法的问题在于这是运行时要求,而不是编译时间。

答案 3 :(得分:0)

你将如何应对

的情况
interface IFoo {
  void MethodA();
  void MethodB();
}
abstract class Base: IFoo {
  public void MethodA() {}
  // MethodB gets implicitly generated
}
class Derived: Base {
  public void MethodB() {}
}

你可以这样做:

Base myBase = ...
myBase.MethodB();

好的,你可以,因为MethodB是隐含的。但是如果您稍后决定从IFoo类中删除接口Base该怎么办?你刚刚打破了Base的契约。解决方案是生成的方法将是显式的接口实现,但这带来了另一种痛苦。

答案 4 :(得分:0)

您可以在方法声明中从'abstract'切换到'virtual'并提供断言:

public abstract void MethodB();

变为

public virtual void MethodB()
{
    Contract.Require( your condition );
}

答案 5 :(得分:0)

我不认为抽象类或接口在您的场景中有任何不公正,而不是按照SOLID原则(特别是:接口隔离原则):https://msdn.microsoft.com/en-us/library/dn178470(v=pandp.30).aspx

它说大型接口应该分成更小和更具体的接口,这样客户端类就不会被强制实现根本不使用的方法。利用这一原则可以解决您的问题。