多继承
OCP原则: 多用继承,少修改
补充
OCP – Open -closed Principle (开闭原则)
应该在不修改现有代码的基础上,引入新的功能
继承的用途: 在子类上实现对基类的增强,实现多态
多态
在面向对象中,父类,子类通过继承联系在一起,如果可以通过一套方法,就可以实现不同表现,就是多态
一个类继承自多个类就是多继承,它将具有多个类的特征
多继承的弊端
多继承很好的模拟了世界,因为事物很少是单一继承,但是舍弃简单,必然引入复杂性,带来了冲突.
多继承的实现会导致编译器设计的复杂增加,所以有些高级编程语言舍弃了类的多继承
C++支持多继承,Java 舍弃了多继承
Java 中,一个类可以实现多个接口,一个接口也可以继承多个接口,Java 的接口很纯粹,只是方法的声明,继承者必须实现这些方法,就具有了这些能力,就能干什么
多继承可能会带来二义性, 比如一个类多继承了猫和狗的类,那子类究竟继承谁的叫声shout呢?
python 多继承的实现
class ClassName(基类列表):
类体
在上图中,左图是多继承(菱形继承),右图是单一继承
多继承带来了路径选择问题,究竟继承哪个父类的特征呢?
Python 中使用MRO(method reslution order 方法解析顺序)解决基类搜索顺序问题
采用C3算法: 在类被创建出来的时候,就计算一个MRO有序列表,C3算法解决了多继承的二义性.
C3算法,解决了继承的单调性,它阻止创建之前版本产生的二义性,求得MRO本质是为了线性化,且确定了顺序.
单调性:假设有A,B,C三个类,C的mro是[C,A,B],那么C的子类mro,A,B的顺序一定是单调的
多继承的缺点
当类很多,继承复杂情况下,继承路径太多,很难说清什么样的继承路径
Python 语法是允许多继承,但Python代码的解释执行,只有执行到时才会发现错误,
因此,在使用过程中,应该尽量避免使用多继承
Mixin
首先看一个类子:
首先有一个基类 Document ,Word 与Pdf 都是其子类
现有如下需求:
在Document 中提供print方法
class Document:
def __init__(self,content):
self.content=content
def print(self):
print(self.content,'in word')
class Word(Document):pass
class Pdf(Document):pass
w = Word('test word string',)
##################
class Document:
def __init__(self,content):
self.content=content
def print(self):
print(self.content,'in word')
class Word(Document):
def print(self):
print(self.content,'in word')
class Pdf(Document):
def print(self):
print(self.content,'in pdf')
w = Word('test word string',)
基类提供的方法可以不具体实现,因为它未必适合子类的打印,子类中需要覆盖重写
基类中只定义,不实现的方法称为"抽象方法,在Python中,如果采用这种方式定义的抽象方法,子类可以不实现,直到子类使用该方法的时候才报错
#父类做统计基本实现
class Document: # 抽象类
def __init__(self ,content):
self.content = content
def print(self):
raise NotImplementedError('我就不实现') # 未实现异常 往往含有此方法,代表该类做为基类,因此该类就变成了抽象类
class Word(Document): # 省掉了不必要的方法
def print(self): # 这里不是全局的print
print(self.content,'~~in word')
class Pdf(Document):
def print(self):
print(self.content,'~~in pdf')
w = Word('test word string')
d =Document('tset string') # 内部含有未实现异常,但是不影响实例化,但不建议对其实例化
#抽象类不实例化,所以下面的子类同样可以对其实例化.但不是一定要实例化.
# 子类覆盖抽象类
需要打印的子类上增加
如果在现有子类word 或PDF上直接增加,违反了OCP原则,所以可以继续在后面增加子类来完成打印功能
class Document: # 第三方库,不允许修改
def __init__(self, content):
self.content = content
class Word(Document)