Python支持有限的多重继承。那它有何限制?

22
2个回答

12

我不确定Python教程的作者指的是哪些限制,但我猜想其中一部分与Python中方法/属性查找的实现方式有关(即“方法解析顺序”或MRO)。Python使用C3超类线性化机制来处理所谓的“菱形继承问题”。

一旦在类层次结构中引入多重继承,任何给定的类都没有唯一一个可能的继承类,它只有“MRO中下一个类”,即使对于期望从特定类继承的类也如此。

例如,如果 class A(object)class B(A)class C(A),并且 class D(B, C),那么类 D 的MRO就是 D->B->C->A。当类B调用super()时,它会得到A上的一个方法。但现在这种情况已经不再成立了;当B调用super()时,如果C存在,则会得到C上的一个方法。

如果在重写的方法中更改方法签名,这可能会导致问题。类B期望在调用super时获得来自类A的方法签名,但实际上却获得了来自C的方法签名,这个方法可能没有该签名(也可能无法从类B的角度实现所需的行为)。

class A(object):
    def __init__(self, foo):
        print "A!"

class B(A):
    def __init__(self, foo, bar):
        print "B!"
        super(B, self).__init__(foo)

class C(A):
    def __init__(self, foo, baaz):
        print "C!"
        super(C, self).__init__(foo)

class D(B, C):
    def __init__(self, foo, bar):
        print "D!"
        super(D, self).__init__(foo, bar)

print D.mro()
D("foo", "bar")
在这段代码示例中,类B和C已经合理地扩展了A,并更改了它们的__init__签名,但正确地调用了它们期望的超类签名。但是当你像这样创建D时,B的有效"超类"变成了C而不是A。当它调用super时,就会出现问题:
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]
D!
B!
Traceback (most recent call last):
  File "/tmp/multi_inherit.py", line 22, in <module>
    D("foo", "bar")
  File "/tmp/multi_inherit.py", line 19, in __init__
    super(D, self).__init__(foo, bar)
  File "/tmp/multi_inherit.py", line 9, in __init__
    super(B, self).__init__(foo)
TypeError: __init__() takes exactly 3 arguments (2 given)
同样的事情也可能发生在其他方法中(如果它们调用了super()),并且“钻石”不一定只出现在类层次结构的根部。

7
这一切都是正确的,但任何具有多重继承的语言都必须处理这些问题。如果我们假设你的答案是正确的,那么什么语言(具有MI)不会有多重继承的限制形式? - Michael J. Barber

5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接