多继承的秘密

继承有两种方式:

1、classname.function(self)

2、super().function()

这两种方法有何区别和弊端呢?代码如下

使用 classname.function(self) 方法来实现继承

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): # 多重继承,使用 classname.function(self) 方式
    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_base_calls, s.num_right_calls, s.num_left_calls, s.num_sub_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
2 1 1 1 # 这里不难看出,基类的call_me被调用了两次,这在某些业务里面会存在BUG

 

使用 super().function() 实现继承

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()
        print("Calling method on Subclass")
        self.num_sub_calls += 1


s = Subclass()
s.call_me()
print(s.num_base_calls, s.num_right_calls, s.num_left_calls, s.num_sub_calls)

结果:
Calling method on base class
Calling method on right subclass
Calling method on left subclass
Calling method on Subclass
1 1 1 1 # 基类的call_me方法只被调用了一次

 

总结:

classname.function(self):Subclass的call_me方法调用了LeftSubclass.call_me(self)和 RightSubclass.call_me(self)方法,他们同时去调基类的call_me方法,所以导致基类的方法被调用了两次。

super().function():Subclass的call_me方法调用了super().call_me(),其实他是先去调 LeftSubclass这个类里面的call_me方法,但这时super引用了 RightSubclass.call_me,并没有直接去访问基类的call_me,而是把权限给了RightSubclass,由RightSubclass去调基类的方法,通过super调用保证了在类的层次结构中,每个方法被调用一次。

posted @ 2020-03-13 21:26  海澜时见鲸  阅读(105)  评论(0)    收藏  举报