C# 应该有多重继承吗? [关闭]

Posted

技术标签:

【中文标题】C# 应该有多重继承吗? [关闭]【英文标题】:Should C# have multiple inheritance? [closed] 【发布时间】:2010-09-16 13:00:32 【问题描述】:

我遇到了许多反对在 C# 中包含多重继承的论点,其中一些包括(撇开哲学论点):

多重继承太复杂而且经常模棱两可 没有必要,因为接口提供了类似的东西 在接口不合适的情况下,组合是一个很好的替代品

我来自 C++ 背景,怀念多重继承的强大和优雅。尽管它并不适合所有软件设计,但在某些情况下,很难否认它对接口、组合和类似的 OO 技术的实用性。

排除多重继承是否意味着开发人员不够聪明,无法明智地使用它们,并且无法在复杂性出现时解决它们?

我个人很欢迎在 C#(可能是 C##)中引入多重继承。


附录:我很想知道来自单一(或程序背景)与多重继承背景的回复。我经常发现没有多重继承经验的开发人员通常会默认使用多重继承是不必要的论点,因为他们没有任何范式经验。

【问题讨论】:

我看不出多重继承有多优雅。 【参考方案1】:

我说不,直到钻石问题(类的多重继承不好的一个重要原因)得到充分解决并且解决方案与使用接口一样好。简而言之,钻石问题基本上与由于类的多重继承而导致类中的数据、方法和事件的潜在歧义有关。

P/S 您“很少”避免使用您急需的编程解决方案,因为它很难。 “困难”不是没有多重继承的借口。多线程很难,但它在 C# 中可用。没有多重继承的一大原因是由于菱形问题(http://en.wikipedia.org/wiki/Diamond_problem)。一个类似的推理适用于您对更好的替代方案的评论(人们以不同的方式解决和思考,所以有时一个解决方案是一个坏主意)和合适的选项已经存在(为什么在 ADO.NET 成功并且成熟时创建 LINQ...由于一个比另一个强。)

【讨论】:

我想知道您所说的“直到解决”是什么意思?任何给定框架的继承语义都将支持公理的某种组合(例如“给定 X:Y:Z 和 X 类型的对象 x,将 x 转换为 Y,然后 Z 将产生与直接转换为 Z 相同的结果”) .不支持多重继承的框架可以支持公理的组合,而这些公理在支持的框架中是不支持的。问题不在于开发框架之一——即使从语义的角度来看,MI 也需要放弃更有用的东西。 @supercat “直到解决”,我并不是说钻石问题解决了。我的意思是提供了一个可接受的解决方法。对我来说,这是一个糟糕的选择。 很公平,尽管值得注意的是,对于 C# 类型的某些公理来说,没有任何类型可以继承多于一种期望其基成员的虚拟实现被使用或期望的其他类型任何既不是祖先也不是后代的类不会访问受保护的基字段。这几乎迫使区分具有这种期望的可继承类型和不具有这种期望的可继承类型。在 Java、.NET 和 C# 中,人们说一种类型不会执行有问题的操作的方式是使其成为接口。 虽然接口比multiply-inheritable-things需要的限制稍微多一些[例如。接口不能定义字段并没有语义上的原因,并且每个实现类型都包含一个隐藏方法,该方法将返回其字段数据的开头和实现该接口字段的“字段”之间的偏移量,也没有接口为什么不能定义字段的原因'不为定义在自身内部的方法定义“默认”实现(甚至那些定义在祖先中的方法,明确的条件是在有歧义的情况下,框架可以任意选择任何合适的方法)【参考方案2】:

我几乎不会错过 C# 中的多重继承。

如果您使用多重继承来定义实际的域模型,那么根据我的经验,您通常可以使用单一继承和一些好的设计模式来创建同样好的设计。

我发现多重继承具有真正价值的大部分地方不是域本身,而是一些需要您使用 MI 的技术/框架约束。使用 ATL 实现 COM 对象是一个很好的例子,说明您使用多重继承来实现 COM 对象所需的所有必要接口,并且是对丑陋(与 .NET 相比)技术的优雅解决方案。从优雅的角度来看,它是一个 C++ 框架!

我现在有一种情况,我可以使用多重继承。我有一个类需要从其他域对象派生功能,但它也需要可用于跨 AppDomain 调用。这意味着它必须从 MarshalByRefObject 继承。所以在这种特殊情况下,我真的很想从 MarshalByRefObject 和我的特定域对象中派生。然而这是不可能的,所以我的类必须实现与我的域对象相同的接口,并将调用转发到聚合实例。

但正如我所说,这是技术/框架施加约束的情况,而不是领域模型本身。

【讨论】:

【参考方案3】:

如果接口可以实现的话,它会让事情变得更简单,更少的代码。但是它们会被误用而不是正确使用吗?我认为,在您看到如何正确完成之前,您不会错过它。我对多重继承不安全的论点感到恼火。它不是。但几乎所有的语言实现都是。但我们需要它吗?,我不知道。

我更喜欢返回类型协方差,这可以很容易地添加(只需放宽规则,在覆盖方法的返回类型上),并且始终是安全的。

示例:

class shape 

class circle : shape 

interface part 
    shape Form();


interface wheel : part 
    circle Form();

【讨论】:

我不确定允许接口(例如IFoo)指定静态类(例如IFooHelpers)如果在编译类C时实现该接口会有什么问题编译器找不到成员的实现(例如int DoSomething(string Bar),它应该自动生成代码int IFoo.DoSomething(string Bar) return IFooHelpers.Classes<C>.DoSomething(C This, string Bar);,假设存在适当的静态类和方法。【参考方案4】:

接口是多重继承。事实上,我认为 Java/C# 类型接口是多重继承的“正确”实现。通过使用接口强制进行多重继承,而不是允许从多个具体或抽象类继承,这会迫使开发人员使用组合/委托来进行代码重用。继承永远不应该用于代码重用,C++ 类型多重继承的缺失迫使开发人员想出设计更好的类。

【讨论】:

接口提供规范,而不是可重用的代码;它们是合同,而不是继承

以上是关于C# 应该有多重继承吗? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

C++ 多重继承的真实例子是啥? [关闭]

使用与多重继承相关的接口的任何真实示例

多重继承,虚基类

java中的多重继承是啥意思?

如何在 C# 中模拟多重继承

C#中继承问题