C#:抽象类需要实现接口吗?

Posted

技术标签:

【中文标题】C#:抽象类需要实现接口吗?【英文标题】:C#: Abstract classes need to implement interfaces? 【发布时间】:2011-02-11 21:45:39 【问题描述】:

我在 C# 中的测试代码:

namespace DSnA

    public abstract class Test : IComparable
    

    

导致以下编译器错误:

error CS0535: 'DSnA.Test' does not implement interface member
'System.IComparable.CompareTo(object)'

既然类Test是一个抽象类,为什么编译器需要它来实现接口呢?这个要求不应该只对具体类强制吗?

【问题讨论】:

哈哈。我写了一件事然后决定改变它。对不起。 :) 基于对已接受答案的反对票和 cmets,我相信反对票的出现是因为问题的措辞方式。 OP 询问“为什么会这样”,这超出了 *** 的范围。我自己也遇到过这个问题,这个问题更像是“我错过了什么吗?我真的必须提供实现吗?这不会破坏它作为抽象类的意义吗?”答案是“不,您不必提供 实现(这将违反抽象类的目的),但这是您必须做的,以使您的情况正常。” 我发现了一个你必须提供实现的案例。这是接口具有可选参数的地方。如果将方法作为抽象包含在基类中,则继承的类在没有可选参数的情况下将无法编译(这违背了可选参数的目的)。在这种情况下,我只是抛出 NotImplementedException。 忽略我之前的评论 - 它没有按预期工作,最小意外原则在这里不适用。 【参考方案1】:

在 C# 中,实现接口的类需要定义该接口的所有成员。对于抽象类,您只需使用 abstract 关键字定义这些成员:

interface IFoo

    void Bar();


abstract class Foo : IFoo

    public abstract void Bar();

或者换一种说法:你不必必须“实现”它(这对抽象类来说是一个可怕的限制);但是,在 C# 中,您必须告诉编译器您故意将责任转嫁给具体的子类 - 上面的代码行显示了如何做到这一点。

抱怨这不是问题的答案的 cmets 和 downvotes 没有抓住重点。有人来到 Stack Overflow,收到了这个编译器错误,但是有一个抽象类,在其中提供一个实现是错误的,没有一个好的解决方案被困住 - 必须编写抛出运行时异常的实现方法,这是一项可怕的工作-around - 直到他们获得上述信息。 C# 要求这种明确性是好是坏都超出了 Stack Overflow 的范围,与问题和答案无关。

【讨论】:

@Ben 刚刚看到你的评论。您可能已经想通了,但以防其他人需要它。查看显式接口实现:msdn.microsoft.com/en-us/library/ms173157.aspx @Joel @Ben 我不认为显式接口可以与抽象类一起使用。在上面的示例代码中,将Foo 中的定义更改为public abstract void IFoo.Bar();,您会收到抱怨“public”和“abstract”不是有效的修饰符。 这并没有回答为什么这甚至是必要的问题,考虑到这是一个抽象类,编译器应该知道如何填补空白。在 Java 中,这不是必需的,它允许一些有用的模式,例如 ioc 容器上的装饰器模式,例如Spring/JavaEE(当您需要装饰托管接口的特定方法时)。 .net 中的相同实现将不得不迫使开发人员非常冗长,尤其是在大型接口上,例如 nhibernate 的 ISession AspectJ 的 mixins 是另一个例子。它允许您将许多抽象类的部分实现混合到一个接口中。每个抽象类只需要实现它想要实现的方法。如果我要在 .net 中重新创建相同的功能,没有愚蠢的抽象方法样板会妨碍我 @Sheepy - 没错,但是,恕我直言,您误解了提问者需要什么,以及这确实是一个“答案”。我也有同样的问题——因为要求提供实现是没有意义的,所以我被卡住了。答案是:您不必必须“实现”它 - 但这是您必须做的告诉编译器你不会去实现它。 (你[正确地]说这不是一个答案的问题,不会是一个合适的***问题 - 它会被简单地关闭为非目的。)【参考方案2】:

与 Java 不同,在 C# 中: “抽象类必须提供该类的基类列表中列出的所有接口成员的实现。但是,允许抽象类将接口方法映射到抽象方法。”

https://msdn.microsoft.com/en-us/library/Aa664595(v=VS.71).aspx

【讨论】:

超级清晰的答案,非常棒,您可以同时提供这两种情况,因为您有时可能还想在基类中实现该行为 这里出现的一个问题是:为什么这些 C# 样板声明(显然它们是)需要存在于抽象类中,否则它们可能会更简洁(从而弄乱类)?在我的 C# 项目中,我有很多抽象类和接口——我大部分时间做的是在 Visual Studio 中复制和粘贴方法声明。【参考方案3】:

它们不必实际实现接口。接口方法/属性也可以是抽象的,甚至是虚拟的。所以由子类来实际实现它们。

【讨论】:

以上是关于C#:抽象类需要实现接口吗?的主要内容,如果未能解决你的问题,请参考以下文章

C#中接口和抽象类

c#中抽象类(abstract)和接口(interface)的相同点与区别

C# 类 - 接口 Interface

继承抽象类,同时实现接口

C#中的抽象类抽象方法和虚方法

c#抽象类实现一个接口