多态

一、接口类与抽象类

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()
复制代码
原文地址:https://www.cnblogs.com/Ebola-/p/8324924.html