我已经看到一些讨论为什么c#没有实现多重继承,但是为什么在vb中不支持它的原因很少。我知道c#和vb都被编译成中间语言,所以他们都需要共享类似的限制。
VB中缺少多重继承似乎是网点缺乏功能的一个原因。有谁知道为什么VB不支持多重继承?我希望有一些历史课和讨论为什么从未考虑过VB。
答案 0 :(得分:14)
它没有在CLR中实现,因此在VB.NET等CLS兼容语言中不可用。微软的工程师似乎已经达成了普遍的共识,包括C#首席架构师Anders Hejlsberg认为潜在的好处不值得实施的成本和复杂性。 Chris Brumme是当时.NET团队的杰出工程师,他在2004年就这样说过:
有几个原因我们没有提供多个实现继承的可编程,可验证,符合CLS的版本:
不同的语言实际上对MI的工作方式有不同的期望。例如,如何解决冲突以及重复的基数是合并还是冗余。在我们在CLR中实现MI之前,我们必须对所有语言进行调查,找出常见概念,并决定如何以语言中立的方式表达它们。我们还必须决定MI是否属于CLS,这对于不想要这个概念的语言(例如VB.NET)意味着什么。当然,这是我们作为公共语言运行时所处的业务,但我们还没有为MI做这件事。
MI真正适合的地方实际上非常小。在许多情况下,多个接口继承可以完成工作。在其他情况下,您可以使用封装和委派。如果我们要添加一个稍微不同的构造,比如mixins,那实际上会更强大吗?
- 醇>
多个实现继承为实现注入了很多复杂性。这种复杂性会影响投射,布局,调度,现场访问,序列化,身份比较,可验证性,反射,泛型,以及可能还有很多其他地方。
这个功能本身并不清楚。这是我们经常被问到的事情。这是我们没有尽职尽责的事情。但是我的直觉告诉我,在我们进行了深入检查后,我们仍然会决定不使用该功能。
[Link]
底线是我不会屏住呼吸。
现在,通过继承多个接口并将实现委托给包含的类实例,您可以获得多个实现继承的一些好处(如果不是大多数好处)。这是一个更多的工作,但它是我们现在最好的。
我还应该注意到,我写了几年C ++全职,并且在我自己的设计中只使用了多次继承。当我需要它时它很方便,但说实话,我并不经常在C#中找到它。
答案 1 :(得分:4)
所有dotNET语言共享一个公共类型系统,并且该CTS不支持多重继承。像VB或C#这样的特定语言不能单独添加它,它将与dotNET的其余部分不兼容。最多一种语言可能会选择忽略/隐藏此类功能。
我不确切地知道为什么不包括这个但是值得注意的是大多数语言都不支持它。我只知道C ++,虽然基本的应用程序很简单,有时很有用但它也带来了大量特殊的语法和规则。并不是每个人都认为它物有所值。
答案 2 :(得分:2)
缺乏MI(多重继承)与语言设计和预期主机(CLR)密切相关:
1)MI / SI的差异是如此基本一种语言,以后很难(或许不可能)“将其添加为特征”。
2)对于预期的主机:虽然 可以为CLR编写MI语言(正如可以为CLR编写带延续的语言等) - 可以这样做,就是这样,你失去了与所有其他“.NET”语言的互操作性。
可以改装到CLR中的更简单的“MI”形式是通过编译时MRO崩溃处理的Traits(这是Scala支持JVM上的Traits的方式)。然而,这仍然需要主要重新设计/重新思考该语言,并且对于像VB(.NET)那样“审查”的东西,祝你好运:-)必须确保它与现有代码一致在为语言添加改进时,这是一个大问题。
答案 3 :(得分:0)
还有许多其他技术被证明远远优于MI,例如构图。即使在像C ++这样支持MI的语言中,实际上很少见到从两个非抽象基类中继承的类。
答案 4 :(得分:0)
为什么C#或VB.NET不支持多重继承
http://royalarun.blogspot.in/2013/05/why-c-or-vbnet-doesnt-support-multiple.html
1)第一个原因是围绕Diamond问题的模糊性,考虑一个类A有foo()方法,然后B和C派生自A并且有自己的foo()实现,现在D类从B和C派生,使用多重继承如果我们只引用foo()编译器将无法决定它应该调用哪个foo()。这也称为Diamond问题,因为此继承方案中的结构类似于4个边缘菱形,见下文
A foo() / \ / \ foo() B C foo() \ / \ / D foo()
在我看来,即使我们删除钻石类A的顶部头部并允许多重遗传,我们也会看到这种含糊不清的问题。
有些时候,如果你把这个理由告诉面试官,他会问C ++是否可以支持多重继承,而不是为什么不支持c#oR vb.net。在这种情况下,我会尝试向他解释我在下面给出的第二个原因,不是因为技术难度更大但更易于维护和清晰的设计是驱动因素,尽管这只能由任何Java设计师确认,我们可以推测。维基百科链接有一些很好的解释,说明在使用多重遗传时,由于钻石问题,不同的语言地址问题是如何产生的。
2)对我来说,第二个也是更有说服力的理由是,多个继承确实使设计复杂化并在转换,构造函数链接等过程中产生问题,并且假设没有多少场景需要多次继承,则明智地决定省略它简单的缘故。也是c#并通过支持接口的单继承来避免这种歧义。由于接口只有方法声明而且没有提供任何实现,因此只有一个特定方法的实现,因此不会有任何歧义。
答案 5 :(得分:0)
假设类型B
有一个虚拟方法m
,其中X
和Y
的实现方式不同,但两个实现都链接到base.m()
,{{1} } {}从D
和X
派生而不定义自己的实现,Y
是George
的实例。类D
将期望没有派生类访问X
而不通过它自己的方法实现,类B.m()
将具有类似的期望。编译器没有任何东西可以Y
做什么,这不会违反这些期望。如果需要从CType(George,B).m()
到D
类型的向上转换类型为B
或X
,则经过Y
的广告可以使用X
经过X
的方法和演员可以使用Y
的方法,但是Y
的引用不会被希望引用{{D
的代码直接使用。 1}}(或者,就此而言,B
)。要求只有接口才能被多重继承,并且实现接口的每个类型都必须提供所有方法的实现,这几乎与提供广义多重继承一样好,但不会导致相同的歧义。