考虑以下 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 的版本)?
所以,当你从孙子调用 super 时,
ChildA
的 __init__
方法将被调用,因为 super 遵循 __mro__
属性(父母从左到右然后祖父母从左到右,然后是曾祖父母,.. .)
由于
ChildA
的init也调用了super,那么所有的super调用将被链接起来,调用子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)
另请注意,在您的代码中,名称和序列号被重用为所有类之间的实例属性,这可能不是您想要的。
Diamond 问题在 Python 中不存在,因为它优先考虑最先继承的类。
class Parent:
def __init__(self, name, serial, **kwargs):
self.name = name
self.serial = serial
def printName(self):
print("Inside P");
class ChildA(Parent):
def __init__(self, a_name, a_serial, **kwargs):
self.a_name = a_name
self.a_serial = a_serial
def printName(self):
print("Inside A");
class ChildB(Parent):
def __init__(self, b_name, b_serial, **kwargs):
self.b_name = b_name
self.b_serial = b_serial
def printName(self):
print("Inside B");
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)
obj = GrandChild();
obj.printName();
输出是A内
在上面的例子中,GrandChild(ChildA, ChildB)表示类GrandChild先继承类ChildA,再继承类ChildB。
一旦你在 D 中声明了 printName() 方法,那么输出将是 Inside GrandChild。如果你在 GC 类中交换继承子的位置,那么:
class GrandChild(ChildB, ChildA):
def __init__(self):
super().__init__(name = "blah", a_name = "a blah", b_name = "b blah", a_serial = 99, b_serial = 99, serial = 30)
obj = GrandChild();
obj.printName();
输出是B里面