多重继承
多重继承概念
多重继承容易引发的问题
问题的解救额方法
多重继承就是子类继承多个父类,原则非常简单。
混入:一个类的存在,是为了被其他类继承并添加额外的功能,不是一个单独存在的超类。
多重继承最简单有效的方式就是混入。
例:C继承A和B,A和B继承0
如果它们分别调用各自的方法,那么便没有影响,如果调用继承自各自超类的方法,那么输出就会和预期不符合
例:
class BaseClass:
num_base_calls =0
def call_me(self):
print("Calling method on Base Class")
self.num_base_calls +=1
class LeftSubclass(BaseClass):
num_left_calls=0
def call_me(self):
BaseClass.call_me(self)
print("Calling method on left Subclass")
self.num_left_calls+=1
class RightSubclass(BaseClass):
num_right_calls=0
def call_me(self):
BaseClass.call_me(self)
print("Calling method on right Subclass")
self.num_right_calls+=1
class Subclass(LeftSubclass,RightSubclass):
num_sub_calls=0
def call_me(self):
LeftSubclass.call_me(self)
RightSubclass.call_me(self)
print("Calling method on Subclass")
self.num_sub_calls+=1
s=Subclass()
s.call_me()
print(s.num_sub_calls,s.num_right_calls,s.num_base_calls,s.num_left_calls)
"各个方法调用次数统计输出"
Calling method on Base Class
Calling method on left Subclass
Calling method on Base Class
Calling method on right Subclass
Calling method on Subclass
1 1 2 1
由上例可见,
他们调用继承自各自超类的方法
s.call_me()时候,
LeftSubclass.call_me(self)首先调用了其父类的方法,然后再调用自身的方法
RightSubclass.call_me(self)首先调用了其父类的方法,然后再调用自身的方法
也就是说,其父类被调用了两次,这是我们不想看到的。
…
所以在多重继承中,
我们目的是:
自下而上调用,在同类层级中的调用“下一个”方法,而不是“父类方法”。 然而,下一个方法不一定属于该类的父类或者更早的祖先。比如上面那个例子,第二层类LeftSubclass类call_me的下一个方法应该是RightSubclass类的call_me,而不是父类的call_me方法。
从上往下输出
因此super可以拯救这个灾难,它最初是为了实现更发杂的多重继承而实现的。
class BaseClass:
num_base_calls =0
def call_me(self):
print("Calling method on Base Class")
self.num_base_calls +=1
class LeftSubclass(BaseClass):
num_left_calls=0
def call_me(self):
super().call_me()
print("Calling method on left Subclass")
self.num_left_calls+=1
class RightSubclass(BaseClass):
num_right_calls=0
def call_me(self):
super().call_me()
print("Calling method on right Subclass")
self.num_right_calls+=1
class Subclass(LeftSubclass,RightSubclass):
num_sub_calls=0
def call_me(self):
super().call_me()
"注意这里只调用了一次,没有用super以前调用了两次"
print("Calling method on Subclass")
self.num_sub_calls+=1
s=Subclass()
s.call_me()
Calling method on Base Class
Calling method on right Subclass
Calling method on left Subclass
Calling method on Subclass
首先,Subclass的call_me方法调用super().call_me(),指向LeftSubclass.call_me().
然后,LeftSubclass.call_me调用super().call_me,这一次super()指向的是RightSubclass.call_me()
接着,RightSubclass.call_me()调用super().call_me,super()指向BaseClass.call_me()
最后再依次返回即
Calling method on Base Class
Calling method on right Subclass
Calling method on left Subclass