考虑下面的python代码片段
class A(object):
def __init__(self, a):
self.a = a
class B(A):
def __init__(self, a, b):
super(B, self).__init__(a)
self.b = b
class C(A):
def __init__(self, a, c):
super(C, self).__init__(a)
self.c = c
class D(B, C):
def __init__(self, a, b, c, d):
#super(D,self).__init__(a, b, c) ???
self.d = d
我想知道如何将a
,b
和c
传递给相应的基类构造函数。
谢谢,
好吧,在处理一般的多重继承时,你的基类(不幸的是)应该设计为多重继承。你的例子中的类B
和C
不是,因此你找不到在super
中应用D
的正确方法。
为多重继承设计基类的常用方法之一是让中级基类在他们不想使用的__init__
方法中接受额外的args,并将它们传递给他们的super
调用。
这是在python中执行此操作的一种方法:
class A(object):
def __init__(self,a):
self.a=a
class B(A):
def __init__(self,b,**kw):
self.b=b
super(B,self).__init__(**kw)
class C(A):
def __init__(self,c,**kw):
self.c=c
super(C,self).__init__(**kw)
class D(B,C):
def __init__(self,a,b,c,d):
super(D,self).__init__(a=a,b=b,c=c)
self.d=d
这可以被视为令人失望,但这就是它的方式。
不幸的是,没有办法在不更改Base类的情况下使用super()
来完成这项工作。对B
或C
的构造函数的任何调用将试图调用Method Resolution Order中的下一个类,它将始终是B
或C
而不是A
和B
类构造函数所假设的C
类。
另一种方法是显式调用构造函数,而不在每个类中使用super()
。
class A(object):
def __init__(self, a):
object.__init__()
self.a = a
class B(A):
def __init__(self, a, b):
A.__init__(self, a)
self.b = b
class C(object):
def __init__(self, a, c):
A.__init__(self, a)
self.c = c
class D(B, C):
def __init__(self, a, b, c, d):
B.__init__(self, a, b)
C.__init__(self, a, c)
self.d = d
这里仍有一个缺点,因为A
构造函数将被调用两次,这在这个例子中并没有太大影响,但可能会导致更复杂的构造函数出现问题。您可以包含一个检查以防止构造函数多次运行。
class A(object):
def __init__(self, a):
if hasattr(self, 'a'):
return
# Normal constructor.
有人会称这是super()
的缺点,从某种意义上来说,它也只是多重继承的一个缺点。钻石继承模式通常容易出错。而且它们的许多变通方法会导致更加混乱且容易出错的代码。有时,最好的答案是尝试重构代码以减少多重继承。