1

考慮以下Python代碼:解決菱形繼承

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) 

當運行在如GrandChild的super功能,什麼是格式化__init__參數,以便ChildA和ChildB都得到正確的參數的正確方法?

另外,如何從GrandChild類中訪問speak方法(ChildA的版本和ChildB的版本)的兩個不同版本?

+1

這似乎不是多重繼承的有效用例。爲什麼不使用組合來代替? – MSeifert

回答

0

所以,當你調用從孫子超,孩子的__init__方法將被調用,因爲超級遵循__mro__財產(父母從左到右再爺爺奶奶左到右,再大的祖父母,...)

既然太陽城娛樂城的初始也調用超級,那麼所有的超級調用將被鏈接,調用子b的__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

在Python中,你can顯式調用特定方法(之一)的父類(ES):

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

需要注意的是在調用此方法時,需要把self中明確。

您也可以 - 像您一樣 - 使用super()的方式,這將稱爲「第一」父。確切的順序是動態的,但默認情況下,它將執行繼承層次結構的從左到右,深度優先,預訂scans。因此,您的super()電話將只能撥打 ChildA

+0

當我在GrandChild類中調用super時,它確實調用了ChildA和ChildB的__init__函數。我驗證這一點的方法是將打印語句放在__init__函數中,並且兩者都打印出來。 –

+0

我不認爲這個訂單是深度優先的,因爲這會稱之爲第一個孩子和第二個孩子之間的盛大父母,這不會發生什麼。每個超級調用只會調用一個新的方法,但是當每個被調用的方法也調用超級方法時,它會鏈接。 –

+0

我澄清了掃描順序。順序是L-> R,先深入(它會在嘗試第二個父母之前嘗試祖父母),但它會在授予父母(預先掃描)之前嘗試父母。 – Niobos