1

다음 파이썬 코드를 고려하십시오 손자의 super 기능을 실행하는 경우해결 다이아몬드 상속

class Parent(object): 
    def __init__(self, name, serial_number): 
     self.name = name 
     self.serial_number = serial_number 


class ChildA(Parent): 
    def __init__(self, name, serial_number): 
     self.name = name 
     self.serial_number = serial_number 
     super(ChildA, self).__init__(name = self.name, serial_number = self.serial_number) 

    def speak(self): 
     print("I am from Child A") 


class ChildB(Parent): 
    def __init__(self, name, serial_number): 
     self.name = name 
     self.serial_number = serial_number 
     super(ChildB, self).__init__(name = self.name, serial_number = self.serial_number) 

    def speak(self): 
     print("I am from Child B") 


class GrandChild(ChildA, ChildB): 
    def __init__(self, a_name, b_name, a_serial_number, b_serial_number): 
     self.a_name = a_name 
     self.b_name = b_name 
     self.a_serial_number = a_serial_number 
     self.b_serial_number = b_serial_number 
     super(GrandChild, self).__init_(something) 

을 ChildA 및 ChildB 모두 올바른 인수를 얻을 수 있도록 __init__ 인수를 포맷하는 적절한 방법은 무엇입니까 ?

또한 GrandChild 클래스 내에서 speak 메서드 (ChildA 버전 및 ChildB 버전)의 두 가지 버전에 어떻게 액세스합니까? 이 방법으로 호출 할 때 명시 적으로 self을 둘 필요가

ChildA.__init__(self, a_name, a_serial) 
ChildB.__init__(self, b_name, b_serial) 

참고 :

+1

다중 상속을위한 유효한 유스 케이스처럼 보이지 않습니다. 대신 컴포지션을 사용하지 않는 이유는 무엇입니까? – MSeifert

답변

0

때문에, 자식 A의 __init__ 메소드가 호출 될 것이다 (부모는 오른쪽에서 왼쪽으로 다음 왼쪽에서 오른쪽으로, 다음 큰 조부모, ... 조부모)

도 슈퍼를 호출하기 때문에 모든 슈퍼 호출이 연결되어 자식 b의 __init__과 부모 init을 호출합니다.

작동하려면 일반적으로 인터페이스가 일관성이 있어야합니다. 즉, 위치 적 논증은 동일한 것을 의미하고 순서대로 있어야합니다.

그렇지 않은 경우 키워드 인수가 효과적 일 수 있습니다.

class parent: 

    def __init(self, name, serial, **kwargs): 
     self.name = name 
     self.serial = serial 

class ChildA(parent): 

    def __init__(self, a_name, a_serial, **kwargs): 
     self.a_name = a_name 
     self.a_serial = a_serial 
     super().__init__(**kwargs) 

class ChildB(Parent): 

    def __init__(self, b_name, b_serial, **kwargs): 
     self.b_name = b_name 
     self.b_serial = b_serial 
     super().__init__(**kwargs) 


class GrandChild(ChildA, ChildB): 
    def __init__(self): 
     super().__init__(name = "blah", a_name = "a blah", b_name = "b blah", a_serial = 99, b_serial = 99, serial = 30) 

또한 코드 이름과 시리얼은 모든 클래스 사이의 인스턴스 속성으로 재사용되며 이는 사용자가 원하는 것이 아닐 수도 있습니다.

0

파이썬에서 명시 적에서 특정 방법 (중 하나) 부모 클래스 (들)를 호출 can.

마찬가지로 "처음"부모를 부를 super() 방법을 사용할 수 있습니다. 정확한 순서는 동적이지만 기본적으로 왼쪽에서 오른쪽, 깊이 우선, 상속 계층 구조의 scans을 미리 주문합니다. 따라서 super() 전화는 ChildA__init__으로 전화 할 것입니다. 당신이 손자에서 슈퍼를 호출 할 때 슈퍼가 __mro__ 속성을 따르기 때문에

+0

GrandChild 클래스에서 super를 호출하면 ChildA와 ChildB의 __init__ 함수가 모두 호출됩니다. 이 방법을 확인하는 방법은 print 문을 __init__ funcitons에 두는 것이고 둘 다 인쇄됩니다. –

+0

첫 번째 자식과 두 번째 자식 사이의 웅장한 부모를 호출 할 것이므로 그 순서가 깊이 우선이라고 생각하지 않습니다. 각 수퍼 콜은 하나의 새로운 메소드 만 호출 할 것이지만, 호출 된 각 메소드가 또한 수퍼를 호출 할 때 연결됩니다. –

+0

스캔 순서가 명확 해졌습니다. 순서는 L-> R, 우선 깊이입니다 (두 번째 부모를 시도하기 전에 조부모가 시도 할 것입니다).하지만 부모가 조만간 선결 검사를하기 전에 시도합니다. – Niobos