我有一个如下界面
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个方法?
答案 0 :(得分:8)
因为C#语言规范是这样说的。第13.4.7节:
与非抽象类一样,抽象类必须提供类的基类列表中列出的接口的所有成员的实现。
为什么C#设计师选择指定这样的语言可能是Eric Lippert最好的答案。我个人猜测减少意外隐藏方法发生的几率,产生很难解释的错误信息。对于接口方法实现,我个人更愿意使用覆盖关键字。但他们选择不这样做。
答案 1 :(得分:1)
它不支持这一点的原因是因为你的超类不符合合同。抽象类强制实现其子类的唯一方法是定义抽象方法。
如果您不希望抽象类定义那些抽象方法,那么您必须告诉子类来实现接口。
问题必须是,为什么在你的超类上有5个抽象方法会出现问题?
答案 2 :(得分:0)
接口确实将契约要求传递给彼此,因此,只要您拥有IFoo
和IBar : 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
它说大型接口应该分成更小和更具体的接口,这样客户端类就不会被强制实现根本不使用的方法。利用这一原则可以解决您的问题。