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