2012-05-20 5 views

답변

12

파이썬 튜토리얼의 작성자가 언급 한 제한 사항에 대해서는 확신 할 수 없지만, 메소드/속성 룩업이 파이썬에서 구현되는 방식과 관련이 있다고 추측 할 수 있습니다 ("메소드 해석 순서" 또는 MRO). 파이썬은 C3 superclass linearization 메커니즘을 사용합니다. 이것은 "The Diamond Problem"으로 불리는 것을 처리하는 것입니다.

클래스 계층 구조에 다중 상속을 도입하면 해당 클래스가 상속하는 하나의 잠재적 인 클래스가 없으며 해당 클래스는 "MRO의 다음 클래스"만 가질 수 있습니다. 그들은 특히 어떤 계급으로부터 상속 받는다. 예를 들어

, class A(object), class B(A), class C(A)class D(B, C)는 다음 클래스 D위한 MRO은 D->B->C->A 인 경우. 클래스 B는 아마도 A에서 내려 왔다고 생각했을 것입니다. 그리고 super()을 호출하면 A에 관한 메소드를 얻을 것입니다. 그러나 더 이상 사실이 아닙니다. B가 super()을 호출하면 C가있는 경우 대신 C에서 메소드를 가져옵니다.

재정의 된 메서드에서 메서드 서명을 변경하면이 문제가 발생할 수 있습니다. 클래스 B는 클래스가 super를 호출 할 때 클래스의 메서드의 서명을 기다리지 않고 대신 서명을 갖고 있지 않은 클래스 B의 관점에서 원하는 동작을 구현하지 않을 수도있는 메서드를 C에서 가져옵니다. 이 코드 샘플에서

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의 유효 "슈퍼 클래스"대신 A.의 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

이 모든 내용은 사실이지만 다중 상속이있는 언어는 이러한 문제를 처리해야합니다. 귀하의 대답이 정확하다고 가정하면 어떤 언어 (MI 포함) *는 다중 상속이 제한적이지 않습니까? –

관련 문제