多继承
ocp原则:多用“继承”,少修改
继承的用途:在子类上实现对基类的增强、实现多态
多态:通过一套方法,实现不同表现。
一个类继承自多个类就是多继承,它将具有多个类的特征。
多继承弊端
C++支持多继承;Java舍弃了多继承
多继承可能会带来二义性,例如,猫和狗都继承自动物类,现在如果一个类多继承了猫和狗类,猫和狗都有shout 方法,子类究竟继承谁的shout呢? 除非万不得已,能不用就不用,会造成代码不可控
解决方案:解决多继承的语言,要解决二义性。深度或者广度优先
Python使用MRO(method resolution order方法解析顺序 类属性的解释顺序)解决基类搜索顺序问题。
MRO三个搜索算法:都是深度优先
- 新式类算法,经典算法的升级,深度优先,重复的只保留最后一个没有解决继承的单调性
- C3算法,在类被创建出来的时候,就计算出一个MRO有序列表。解决了继承的单调性
Mixin
需求:为Document提供print方法
class Document:
def __init__(self, content):
self.content = content
def print(self): # 抽象方法 只定义,不实现,直到子类使用该方法的时候才报错
raise NotImplementedError()
class Word(Document): pass
# def prints(self):
# print('test',self.content)
class Pdf(Document): pass
t = Word() # 实例化
t.prints()
#用装饰器增强一个类,把功能给类附加上去,哪个类需要,就装饰他(就比如我要在Word函数里面打印他的名字)
class Document:
def __init__(self, name):
self.name = name
# def prints(self): # 抽象类
# raise NotImplementedError
class Word(Document): pass # 如果这个是第三方库不能用的话,就要继承他然后再里面操作
def printname(cls): # 我是一个装饰器 代表一个类就是cls,约定俗成。
def print_name(self):
print('The document name is : {}'.format(self.__class__))
cls.print = print_name # 一个类里的打印属性(方法)等于一个函数(function)
return cls # 把函数返回 Worable 还是原来的值,只不过额外加了属性
@printname # Wordable = printname(Wordable)
class Wordable(Word): pass
test = Wordable(1)
test.print()
print(Wordable.mro()) # 显示方法查找顺序,基类的元组
除了用装饰器,还可以用Mixin方法,也可以得到同样的效果,但是Mixin是类,可以继承。
装饰器和Mixin两者的区别
装饰器是修改当前类,Mixin是继承 多了一个父类
Mixin使用原则
- 不应该显示的出现_/_init__初始化方法
- 不能独立的工作
- Mixin类的祖先类也应是Mixin类
使用时:Mixin类通常在继承列表的第一个位置,例如 class PrintableWord(PrintableMixin, Word):pass
class Document:
def __init__(self, name):
self.name = name
class Word(Document): pass # 如果这个是第三方库不能用的话,就要继承他然后再里面操作
class PrintableMixin: # Mixin方法
def print(self):
print(self.name, 'Mixin')
class Wordable(PrintableMixin, Word): pass # Mixin类通常在继承列表的第一个位置
test = Wordable(1)
test.print()
print(Wordable.mro()) # 查找循序
练习:
1、Shape基类,要求所有子类都必须提供面积的计算,子类有三角形、圆。
2 、对圆进行 json 序列化 Mixin 实现,和用装饰器实现
import math
class Shape:
def area(self): # 抽象类
raise NotImplementedError()
class Triangle(Shape):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def area(self):
p = (self.a + self.b + self.c) / 2
return math.sqrt(p * (p - self.a) * (p - self.b) * (p - self.c))
import json
class Circle(Shape):
def __init__(self, r):
self.r = r
def area(self):
return math.pi * (self.r ** 2)
class CiccleshapeMixin: # 定义一个mixin类
def dums(self, t='json'):
if t == 'json':
return json.dumps(self.__dict__)
else:
pass
class Cir(CiccleshapeMixin,Circle):pass # 继承并发扬光大
a = Cir(4)
print(a.area())
print(a.dums())
----
def jsos(cls): # 装饰器实现
def jss(self):
return json.dumps(self.__dict__)
cls.print = jss
return cls
@jsos # jsos = jsos(Circle)
class Circle(Shape):
if __name__ = __main__:
a = Circle(4)
print(a.area(), a.print())
2.用面向对象实现Linkedlist链表
1.单向链表实现append、iternodes方法