45

C# 编程语言中,Krzysztof Cwalina 在注释中指出:

我们明确决定不添加对多重继承的支持 [...] 多重继承的缺乏迫使我们添加接口的概念,这反过来又导致了框架演变、更深的继承层次结构和许多其他问题问题。

接口是面向对象编程语言的核心概念。我不遵循“强迫我们添加接口的概念”的意思

Krzysztof 是否意味着必须针对接口的使用做出某些设计决策,否则将使用多重继承?或者,他的意思是interface's 是因为缺少多重继承而被引入 C# 的?你能举个例子吗?

4

4 回答 4

25

接口只是一个没有数据成员并且只定义public abstract方法的基类。例如,这将是 C++ 中的接口:

class IFrobbable {
    public:
    virtual void Frob() = 0;
}

因此,当 MI 可用作语言功能时,您可以通过简单地从它们派生来“实现”接口(同样,C++):

class Widget : public IFrobbable, public IBrappable {
    // ...
}

一般情况下的多重继承会引发许多问题和问题,这些问题不一定只有一个答案,甚至对于您对“好”的特定定义(可怕的钻石,有人吗?)来说甚至是一个好的答案。多接口实现回避了大多数这些问题,因为“继承”接口的概念是继承成熟类的一个非常受限的特殊情况。

这就是“迫使我们添加接口的概念”的地方:当只限于单继承时,你不能做太多的 OO 设计,例如,当代码重用实际上是其中之一时,无法重用代码存在严重问题OO 最常见的论点。您必须做更多的事情,下一步是添加多重继承,但仅适用于满足接口约束的类。

因此,我将 Krzysztof 的名言解释为

一般情况下的多重继承是一个非常棘手的问题,鉴于现实生活对.NET 开发的限制,我们无法以令人满意的方式解决它。然而,接口继承在 OOP 中处理起来更简单,而且非常重要,所以我们确实把它放进去了。当然,接口也有自己的一系列问题,主要是关于 BCL 的结构。

于 2013-01-23T15:06:41.613 回答
11

克里斯布鲁姆

我们不直接实现多重实现继承的原因有很多。(如您所知,我们支持多接口继承)。

我认为 Krzysztof Cwalina 在引用中所说的不是接口本身的概念,而是作为多重继承方法的多重接口继承。

我们没有提供内置的、可验证的、符合 CLS 的多重实现继承版本有几个原因:

  1. 不同的语言实际上对 MI 的工作方式有不同的期望。例如,如何解决冲突以及重复碱基是合并还是冗余。在我们可以在 CLR 中实现 MI 之前,我们必须对所有语言进行调查,找出共同的概念,并决定如何以与语言无关的方式来表达它们。我们还必须决定 MI 是否属于 CLS,以及这对于不想要这个概念的语言(例如 VB.NET)意味着什么。当然,这就是我们作为公共语言运行时所从事的业务,但我们还没有为 MI 做这件事。

  2. 真正适合 MI 的地方实际上很少。在许多情况下,多接口继承可以代替完成工作。在其他情况下,您可以使用封装和委托。如果我们要添加一个稍微不同的结构,比如 mixins,那实际上会更强大吗?

  3. 多重实现继承给实现注入了很多复杂性。这种复杂性会影响铸造、布局、调度、字段访问、序列化、身份比较、可验证性、反射、泛型,可能还有很多其他地方。

于 2013-01-23T14:55:41.263 回答
5

我认为您应该阅读 Eric Lippert 所说的内容Interfaces。他的手很脏,所以我认为他比其他人都清楚。

有时有更坏的情况和最坏的情况。你必须选择不那么糟糕的那个。

以下是链接帖子的副本:


它们只是为了确保上述功能(在接口中)在继承类中实现。

正确的。这是一个足够令人敬畏的好处来证明该功能的合理性。正如其他人所说,接口是实现某些方法、属性和事件的合同义务。静态类型语言的引人注目的好处是编译器可以验证您的代码所依赖的契约是否真正得到满足。

也就是说,接口是表示合同义务的一种相当薄弱的方式。如果您想要一种更强大、更灵活的方式来表示合同义务,请查看 Visual Studio 最新版本附带的代码合同功能。

C# 是一门很棒的语言,但有时它会给你一种感觉,首先是微软制造了问题(不允许多重继承),然后提供了解决方案,这是一个相当乏味的解决方案。

好吧,我很高兴你喜欢它。

所有复杂的软件设计都是对相互冲突的功能进行权衡的结果,并试图找到以小成本带来大收益的“最佳位置”。我们从痛苦的经历中了解到,为了实现共享而允许多重继承的语言具有相对较小的好处和相对较大的成本。只允许在不共享实现细节的接口上进行多重继承,可以在没有大部分成本的情况下提供多重继承的许多好处。

于 2013-01-23T15:03:15.683 回答
2

我认为 Cwalina 的语言有点强,关于历史并不完全准确。

请记住,接口在 C# 之前就已经存在,所以说“我们必须添加接口来解决问题 x”对我来说听起来不对。我认为默认情况下接口会存在 - 它们必须存在。

另外,请记住,C# 很大程度上源自 C++。或者,至少,参与创建 C# 语言的人在 C++ 方面具有很强的背景。多重继承是 C++ 中公认的噩梦领域。从多个类继承,这些类本身可能从 commonm 基类派生,确定哪个实现优先等。我的意思是,这是一个非常强大的功能,但无疑会导致复杂的代码。

我怀疑他们放弃了 C# 的多重继承,因为他们(语言作者)知道一切都会变得多么复杂,他们想避免这种情况。还要记住,当 C# 被引入时,它的卖点之一就是它的简洁性(当然没有 Java 干净,但比 C 和 C++ 干净得多)。

Incidentally, in 10+ years of C# development I have only wished for multiple inheritance once. A UI component which I wanted to inherit both a visual style and some common behaviour. It didn't take me long to realise that what I was intending to do would have been a pretty awful design in any case.

于 2013-01-24T12:52:33.063 回答