简体   繁体   English

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

[英]How to partially implement a contract in an abstract base class?

I have a interface as follows 我有一个如下界面

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

I have two method contracts in the interface MethodA and MethodB. 我在MethodA和MethodB接口中有两个方法契约。 I will define set of classes that will implement the above interface. 我将定义将实现上述接口的类集。 Out of these two methods MethodA is common for all the types that will implement the interface. 在这两种方法中,MethodA对于将实现该接口的所有类型都是通用的。 I can define a abstract class as follows 我可以定义一个抽象类,如下所示

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

        public abstract void MethodB();
    }

And inherit this class to all the types that need to implement the above interface. 并将此类继承到需要实现上述接口的所有类型。 It works. 有用。

But here in the abstract class i add 'public abstract void MethodB();'. 但是在抽象类中我添加了'public abstract void MethodB();'。 It looks like repetition of the MethodB contract. 它看起来像是重复MethodB合约。

Why C# does not permit partial interface implementation if the class is abstract?. 如果类是抽象的,为什么C#不允许部分接口实现? The above interface has only two methods. 上面的接口只有两种方法。 suppose one interface has 10 methods and 5 are common functionality and 5 are not, we are forced to add the 5 methods that are not common in the abstract class? 假设一个接口有10个方法,5个是常用功能,5个不是,我们被迫添加抽象类中不常见的5个方法?

Because the C# language specification says so. 因为C#语言规范是这样说的。 Chapter 13.4.7: 第13.4.7节:

Like a non-abstract class, an abstract class must provide implementations of all members of the interfaces that are listed in the base class list of the class. 与非抽象类一样,抽象类必须提供类的基类列表中列出的接口的所有成员的实现。

Why the C# designers chose to specify the language like this is probably best answered by Eric Lippert. 为什么C#设计师选择指定这样的语言可能是Eric Lippert最好的答案。 I'd personally guess at reducing the odds that unintended method hiding occurs, producing error messages that are very hard to interpret. 我个人猜测减少意外隐藏方法发生的几率,产生很难解释的错误信息。 I would personally have been more comfortable requiring the use of the overrides keyword for the interface method implementation. 对于接口方法实现,我个人更愿意使用覆盖关键字。 But they chose not to. 但他们选择不这样做。

The reason it doesn't support this is because your superclass doesn't fulfil the contract. 它不支持这一点的原因是因为你的超类不符合合同。 The only way for an abstract class to force implementation on its subclasses is to define abstract methods. 抽象类强制实现其子类的唯一方法是定义抽象方法。

If you don't want the abstract class to have those abstract methods defined then you have to tell the subclasses to implement the interface instead. 如果您不希望抽象类定义那些抽象方法,那么您必须告诉子类来实现接口。

Question would have to be, why would it be a problem having 5 abstract methods on your superclass? 问题必须是,为什么在你的超类上有5个抽象方法会有问题?

You can switch from 'abstract' to 'virtual' in the method declaration and provide an assertion: 您可以在方法声明中从“abstract”切换到“virtual”并提供断言:

public abstract void MethodB();

becomes

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

Interfaces do pass along the contract requirement to each other, so as far as you have IFoo and IBar : IFoo , then classes inheriting from IBar must implement both interfaces, as clearly IBar cannot implement the members of IFoo itself. 接口确实将契约要求传递给彼此,因此只要你有IFooIBar : IFoo ,那么从IBar继承的类必须实现这两个接口,因为IBar无法实现IFoo本身的成员。 Why this behavior could not be extended to abstract base classes, I don't know. 为什么这种行为无法扩展到抽象基类,我不知道。 I'm sure there is a good reason, and since Hans posted the spec, it's obviously intentional. 我确信这是有充分理由的,因为汉斯发布了规范,这显然是故意的。

As a please do not try this at home approach, you could do something like 作为一个请不要尝试这种在家的方法,你可以做类似的事情

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

Which has the abstract base implement the methods it wants and then force the derived classes to implement the rest by enforcing that the derived classes implement the interface. 哪个抽象基础实现了它想要的方法,然后强制派生类通过强制派生类实现接口来实现其余的。 The derived classes would then be responsible for implementing the methods that are not already in the base class. 然后,派生类将负责实现基类中尚不存在的方法。 The problem with this approach is that this is a runtime requirement, not compile time. 这种方法的问题在于这是运行时要求,而不是编译时间。

How would you handle a situation where you have 你会如何处理你的情况?

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

Could you then do this: 你能这样做吗:

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

Ok you could, since MethodB is implicit. 好的,你可以,因为MethodB是隐含的。 But what if you would later decide to remove the interface IFoo from the Base class? 但是如果你以后决定从Base类中删除接口IFoo怎么办? You just broke the Base 's contract..Solution would be that generated methods would be explicit interface implementations, but that brings another kind of pain. 你刚刚打破了Base的合同。解决方案是生成的方法将是显式接口实现,但这带来了另一种痛苦。

I don't think abstract class or interface is doing any injustice in your scenario rather as per SOLID principles (specifically: Interface Segregation Principle) : https://msdn.microsoft.com/en-us/library/dn178470(v=pandp.30).aspx 我不认为抽象类或接口在您的场景中做任何不公正,而不是根据SOLID原则(特别是:接口隔离原则): https ://msdn.microsoft.com/en-us/library/dn178470( v = pandp) 0.30),的.aspx

It says large interfaces should be split into smaller and more specific ones so that client classes are not forced to implement methods they do not use at all. 它说大型接口应该分成更小和更具体的接口,这样客户端类就不会被迫实现它们根本不使用的方法。 Utilizing this principle would solve your problem. 利用这个原则可以解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM