2012-05-20 3 views

ответ

12

Я не уверен, какие ограничения использовал автор учебника python, но я бы предположил, что отчасти это связано с тем, как метод/атрибут ищет реализован в python («порядок разрешения метода», или MRO). Python использует механизм C3 superclass linearization; это относится к тому, что называется «The Diamond Problem».

После того, как вы ввели множественное наследование в свою иерархию классов, у любого данного класса нет ни одного потенциального класса, на который он наследуется, он имеет только «следующий класс в MRO», даже для классов, которые ожидают, что они наследуют от некоторого класса в частности.

Например, если class A(object), class B(A), class C(A) и class D(B, C), то МРО для класса D является D->B->C->A. Класс B мог быть написан, вероятно, был, думая, что он опускается от A, и когда он называет super() сам по себе, он получит метод на A. Но это уже не так; когда B вызывает super(), он получит метод на C, если он существует.

Если вы меняете сигнатуры методов в переопределенных методах, это может быть проблемой. Класс B, ожидающий подписи метода из класса A, когда он вызывает super, вместо этого получает метод из 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 имеют достаточно протянули, и изменили свои __init__ подписей, но правильно называть их ожидаемый суперкласс подписи. Но когда вы делаете D так, эффективный «суперкласс» из B становится C вместо А. Когда он называет супер, все взрывать:

[<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

Все это верно, но любой язык с множественным наследованием должен решать эти проблемы. Если мы предположим, что ваш ответ правильный, то какой язык (с МИ) * не будет иметь * ограниченную форму множественного наследования? –

 Смежные вопросы

  • Нет связанных вопросов^_^