python之路_面向对象三大特性之继承、多态
一、接口类与抽象类
1、实现接口类和抽象类的语法
from abc import abstractclassmethod, ABCMeta class 父类(mateclass=ABCMeta): # 抽象类/接口类 @abstractclassmethod def function(): pass
2、接口类
继承有两种用途:(1)继承基类的方法,并做出自己的改变和扩展;(2)声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能。
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。
接口类:可以多继承,且最好不实现具体功能
from abc import abstractmethod,ABCMeta class Payment(metaclass=ABCMeta): #抽象类/接口类:子类的规范 @abstractmethod def payment(self,money):pass class Applepay(): def payment(self,money): print('apple 支付了 %d元'%money) class Alipay(): def payment(self,money): print('支付宝 支付了 %d元' % money) class Wechatpay(): def payment(self,money): print('微信 支付了 %d元' % money) def pay(pay_obj,money): #归一化设计 pay_obj.payment(money) apple = Applepay() ali = Alipay() wechat = Wechatpay() pay(wechat,100) pay(apple,200) pay(ali,300)
依赖倒置原则:
高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程。
3、抽象类
与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。 如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
抽象类:最好单继承,且可以简单的实现功能
例1:抽象类可以简单的实现功能
from abc import abstractmethod,ABCMeta class Foo(metaclass=ABCMeta): #抽象类 @abstractmethod def read(self): f = open() f.close() @abstractmethod def write(self): f = open() f.close() class File(Foo): def read(self): super().read() def write(self): super().write() class Disk(Foo): def read(self): super().read() def write(self): super().write()
例2:抽象类不实现功能
#一切皆文件 import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定义抽象方法,无需实现功能 def read(self): '子类必须定义读功能' pass @abc.abstractmethod #定义抽象方法,无需实现功能 def write(self): '子类必须定义写功能' pass
class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('文本数据的读取方法') def write(self): print('文本数据的读取方法') class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的读取方法') class Process(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('进程数据的读取方法') def write(self): print('进程数据的读取方法') wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #这样大家都是被归一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read()
二、钻石继承
1、经典类与新式类
父类继承object类,称为新式类,否则称为经典类,python3中只有新式类,而python2中同时存在两种类。
class A(object): #新式类,若不继承object则变成经典类 def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class D(B): def test(self): print('from D') class E(C): def test(self): print('from E') class F(D,E): pass f1=F() f1.test() print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
#新式类继承顺序:F->D->B->E->C->A #经典类继承顺序:F->D->B->A->E->C #python3中统一都是新式类 #pyhon2中才分新式类与经典类
2、继承顺序
如上例,若F类没有test()方法,则会按照继承的属性向上所继承的类进行寻找,找到位置。但是不同的类(新式或者经典)继承的顺序是不同的。其中新式类和经典类继承的顺序如下:
钻石继承:新式类为广度优先,经典类为深度优先的原则进行继承,其中在新式类中可以用:子类名.__mro__ 查看继承顺序,而经典类中此方法不存在。
三、多态特性
python天生支持多态性。
1、多态
指的同一事物有多种形态,如动物有:人、狗、猪形态
import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): pass class People(Animal): #动物的形态之一:人 def talk(self): print('say hello') class Dog(Animal): #动物的形态之二:狗 def talk(self): print('say wangwang') class Pig(Animal): #动物的形态之三:猪 def talk(self): print('say aoao')
2、多态性
多态性是指在不考虑实例类型的情况下使用实例。
peo=People() dog=Dog() pig=Pig() #peo、dog、pig都是动物,只要是动物肯定有talk方法 #于是我们可以不用考虑它们三者的具体是什么类型,而直接使用 peo.talk() dog.talk() pig.talk() #更进一步,我们可以定义一个统一的接口来使用 def func(obj): obj.talk()