Python中多重继承

梦想的初衷 提交于 2019-12-29 23:23:13

多重继承和方法解析顺序

python支持多继承的,下面看一个多继承的例子:

class A:
    def ping(self):
        print('ping:',self)

class B(A):
    def pong(self):
        print('pong:',self)
        
class C(A):
    def pong(self):
        print('PONG',self)
        
class D(B,C):
    def ping(self):
        super().ping()
        print('post-ping:',self)
    
    def pingpong(self):
        self.ping()
        super().ping()
        self.pong()
        super().pong()
        C.pong(self)

上面的代码用下面的流程图记录为:其中左边为菱形UML图形,右边为上面代码的解析图;
在这里插入图片描述
在C上调用pong有两种方式:

d = D()
d.pong()
>>>pong: <__main__.D object at 0x0000019F560A11C8>
C.pong(d)#超类中的方法都可以直接调用,这时候要把实例参数作为显示参数传入;
>>>PONG <__main__.D object at 0x0000019F560A11C8>
d.pingpong()
>>> post-ping: <__main__.D object at 0x0000019F560A11C8>
	ping: <__main__.D object at 0x0000019F560A11C8>
	pong: <__main__.D object at 0x0000019F560A11C8>
	pong: <__main__.D object at 0x0000019F560A11C8>
	PONG <__main__.D object at 0x0000019F560A11C8>

Python能区分d.pong()调用的是哪个方法,是因为python会按照特定的顺序遍历继承图,这个顺序叫做方法解析顺序。调用d.pingpong()时依次执行下面步骤:

  • 第一个调用self.ping(),运行的是D中的ping,输出前两行;
  • 第二个调用超类的ping,跳过D中的ping,找到类A中ping
  • 第三个调用的是pong,找到的是B类的pong
  • 第四个调用的是超类的pong,找到的也是B类的pong
  • 第五个调用C类的pong

处理多重继承

Python支持多继承,其实好多语言都不支持多继承,因为多继承容易出现很多错误的情况,因此python中也应该谨慎使用多继承。
1. 接口继承与实现继承
在使用多重继承时,一定要明确一开始为什么创建子类,主要原因可能有:

  • 继承接口,创建子类型,实现‘是什么’关系;
  • 继承实现,通过重用避免代码重复
    通过继承重用代码是实现细节,通常可以换用组合和委托模式,而接口则是框架的支柱;

2. 使用抽象基类显式表示接口
如果类的作用是定义接口,应该明确把他定义为抽象基类,关于抽象基类与接口
前文已经介绍过,可点击查看

3. 通过混用重用代码
如果一个类的作用是为多个不相关的子类实现方法,从而使用重用,但不体现‘是什么’关系,应该把那个类明确的定义为混入类,从概念上说,混入不定义新类型,只是打包方法,便于重用,混入类绝对不能实现实例化,而且具体类不能只继承混入类,混入类应该提供某方面的特定行为,只实现少量关系;

4. 在名称中明确知名混入
Python中没有把类声明为混入的正规方式,所以一般在写的时候都建议加入…Mixin后缀。

5. 抽象基类可以作为混入,但是反过来不支持
抽象基类可以实现具体方法,因此也可以作为混入使用,不过,抽象基类定义类型,但是混入做不到。此外,抽象基类可以作为其他类的唯一基类,但是混入类不可以;
抽象基类有个局限:抽象基类中实现的方法只能与抽象基类及其超类中的方法协作;

6. 不要子类化多个具体类
具体类可以没有,或者只有一个具体超类,也就是说,具体类的超类中除了这个具体超类之外,其余的都是抽象基类或者混入;

7. 为用户提供聚合类
聚合类就是抽象类或者混入的组合;

8. 优先使用对象组合,而不是类继承

参考文献:流畅的python, Luciano Ramalho编著

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!