day24-抽象类与接口类

接口类

一、继承有两种用途:
一:继承基类的方法,而且作出本身的改变或者扩展(代码重用)
二:声明某个子类兼容于某基类,定义一个接口类,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,而且实现接口中的功能java

二、例子:python

第一步:每定义一种支付类,就经过实例化对象调用相应的支付方法,这样虽然也能够实现QQ支付和支付宝支付,但代码风格不统一
class QQPay():
    def pay(self, money):
        print('QQ支付了%s元' %money)
        
class AliPay():
    def pay(self, money):
        print('支付宝支持了%s元' %money)
qq1 = QQPay()
ali1 = AliPay()
qq1.pay(100)
ali1.pay(200)

结果:
QQ支付了100元
支付宝支持了200元

第二步:定义一个统一支付的函数,经过将实例化对象做为参数传递给这个函数,由函数来执行实例化对象的pay方法
class QQPay():
    def pay(self, money):
        print('QQ支付了%s元' %money)
        
class AliPay():
    def pay(self, money):
        print('支付宝支持了%s元' %money)

def pay(obj, money):
    obj.pay(money)

qq1 = QQPay()
ali1 = AliPay()

pay(qq1, 100)
pay(ali1, 200)
结果:
QQ支付了100元
支付宝支持了200元

第三步:若是代码后期须要增长新的支付方式,而这时开发人员已经更换,新的开发人员并无依照原来的代码风格进行统一编写,虽然也能够执行,但又破坏了代码统一性
class WechatPay(payment):
    def fuqian(self, money):
        print('微信支付了%s元' %money)

wechat1 = WechatPay()
结果:微信支付了300元

第四步:咱们先定义一个父类,什么都不写,只是要求继承个人全部类有一个pay方法,这样就制定了一个规范,这就叫作接口类,或者抽象类.
class payment:
    def pay(self):
        pass

class QQPay(payment):
    def pay(self, money):
        print('QQ支持了%s元' %money)
        
class AliPay(payment):
    def pay(self, money):
        print('支付宝支持了%s元' %money)
        
class WechatPay(payment):
    def pay(self, money):
        print('微信支付了%s元' %money)

def pay(obj, money):
    obj.pay(money)

qq1 = QQPay()
ali1 = AliPay()
wechat1 = WechatPay()

pay(qq1, 100)
pay(ali1, 200)
pay(ali2, 300)

结果:
QQ支持了100元
支付宝支持了200元
微信支付了300元

可是这样若是新增的方法WechatPay仍然没有遵循父类中的格式,仍是写成了下面这样也仍是能够执行的
class WechatPay(payment):
    def fuqian(self, money):
        print('微信支付了%s元' %money)
wechat1 = WechatPay()
wechat1.fuqian(300)

第五步:那么如何强制让新增的类遵循统一格式呢,须要使用@abstractmethod方法
from abc import ABCMeta, abstractmethod

class payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self):
        pass

class QQPay(payment):
    def pay(self, money):
        print('QQ支持了%s元' %money)
        
class AliPay(payment):
    def pay(self, money):
        print('支付宝支持了%s元' %money)
        
class WechatPay(payment):
    def fuqian(self, money):
        print('微信支付了%s元' %money)

def pay(obj, money):
    obj.pay(money)

qq1 = QQPay()
ali1 = AliPay()
wechat1 = WechatPay()

pay(qq1, 100)
pay(ali1, 200)
wechat1.fuqian(300)
这时若是WechatPay里面方法名称不是pay,那么结果会报错,TypeError: Can't instantiate abstract class WechatPay with abstract methods pay
因此这时就必需要求WechatPay里面存在pay方法,程序才能正确执行,这样就可使用统一的pay函数进行统一调用对象,
代码修改以下:
class WechatPay(payment):
    def pay(self, money):
        print('微信支付了%s元' %money)

qq1 = QQPay()
ali1 = AliPay()
wechat1 = WechatPay()

pay(qq1, 100)
pay(ali1, 200)
pay(wechat1, 300)

备注:经测试,其实子类中只要有父类中的方法pay便可,即便写成下面这样也仍是能够执行。。。
class WechatPay(payment):
    def fuqian(self, money):
        print('微信支付了%s元' %money)
    def pay(self):
        pass

wechat1 = WechatPay()
wechat1.fuqian(300)


也能够将对象放在一个字典中进行循环调用
def pay(obj, money):
    obj.pay(money)

qq1 = QQPay()
ali1 = AliPay()
wechat1 = WechatPay()

pay_dict = {qq1: 100, ali1: 200, wechat1: 300}
for i in pay_dict:
    pay(i, pay_dict[i])

QQ支持了100元
支付宝支持了200元
微信支付了300元
View Code

 

实践中,继承的第一种含义意义并不很大,甚至经常是有害的。由于它使得子类与基类出现强耦合。git

继承的第二种含义很是重要。它又叫“接口继承”。github

接口继承实质上是要求“作出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的全部对象”——这在程序设计上,叫作归一化。编程

归一化使得高层的外部使用者能够不加区分的处理全部接口兼容的对象集合设计模式

依赖倒置原则:
1)高层模块不该该依赖低层模块,两者都应该依赖其抽象;微信

2)抽象不该该依赖细节,细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程ide

在python中根本就没有一个叫作interface的关键字,上面的代码只是看起来像接口,其实并无起到接口的做用,子类彻底能够不用去实现接口 ,若是非要去模仿接口的概念,能够借助第三方模块:
http://pypi.python.org/pypi/zope.interface
twisted的twisted\internet\interface.py里使用zope.interface
文档https://zopeinterface.readthedocs.io/en/latest/
设计模式:https://github.com/faif/python-patterns函数

接口提取了一群类共同的函数,能够把接口当作一个函数的集合,而后让子类去实现接口中的函数。
这么作的意义在于归一化,就是只要是基于同一个接口实现的类,那么全部的这些类产生的对象在使用时,用法都同样。测试

归一化,让使用者无需关心对象的类是什么,只须要知道这些对象都具有某些功能就能够了,这极大地下降了使用者的使用难度。

好比:咱们定义一个动物接口,接口里定义了有跑、吃、呼吸等接口函数,这样老鼠的类去实现了该接口,松鼠的类也去实现了该接口,由两者分别产生一只老鼠和一只松鼠送到你面前,即使是你分别不出哪只是什么鼠你确定知道他俩都会跑,都会吃,都能呼吸。

再好比:咱们有一个汽车接口,里面定义了汽车全部的功能,而后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,你们只须要学会了怎么开汽车,那么不管是本田,仍是奥迪,仍是大众咱们都会开了,开的时候根本无需关心我开的是哪一类车,操做手法(函数调用)都同样

抽象类

一、什么是抽象类
与java同样,python也有抽象类的概念可是一样须要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

二、为何要有抽象类
若是说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
好比咱们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远没法吃到一个叫作水果的东西。

从设计角度去看,若是类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
从实现角度来看,抽象类与普通类的不一样之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点相似,但实际上是不一样的

三、抽象类与接口类抽象类的本质仍是类,指的是一组类的类似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的类似性。抽象类是一个介于类和接口之间的一个概念,同时具有类和接口的部分特性,能够用来实现归一化设计 在python中,并无接口类这种东西,即使不经过专门的模块定义接口,咱们也应该有一些基本的概念。

相关文章
相关标签/搜索