python学习笔记 day25 接口类

1. 接口类 VS 抽象类

接口类:python 原生不支持,多继承时使用,且接口类中所有方法均不实现(pass);

抽象类: python原生支持,不支持多继承,抽象类中的方法可以有代码的实现;

接口类和抽象类都是用来规范子类的

先来看一个例子:比如说我们想实现几种方式的支付功能:按照以前学的,完全可以胜任,就是定义类,对类实例化为对象调用里面的方法;

class Wechat():
    def pay(self,money):
        print("使用微信支付%s"%money)
class Alipay():
    def pay(self,money):
        print("使用支付宝支付%s"%money)
wechat=Wechat()
wechat.pay(100)
alipay=Alipay()
alipay.pay(200)

运行结果:

但其实用户是不关心使用哪种方式去调用的,所以我们可以这样:

class Wechat():
    def pay(self,money):
        print("使用微信支付%s"%money)
class Alipay():
    def pay(self,money):
        print("使用支付宝支付%s"%money)
def Pay(pay_obj,money):
    pay_obj.pay(money)

wechat=Wechat()
# wechat.pay(100)
alipay=Alipay()
# alipay.pay(200)
Pay(wechat,100)
Pay(alipay,200)

这有点类似于内置函数,就是我们用户不想管里面复杂的实现,比如计算某一对象的长度L.__len__(),而是最好给我封装成函数,我直接传个参数len(L)

针对上面改造之后的情况,用户调用起来是很方便,但是如果某一天需要另外一个人实现另一个支付功能,比如苹果支付,但是类中用于支付的函数并不是pay,而是别的名字,那直接调用Pay(pay_obj,money)肯定会报错,因为函数Pay(pay_obj,money)中执行pay_obj.pay(money)时肯定会报错的,因为Applepay类中并没有pay这个方法:

class Wechat():
    def pay(self,money):
        print("使用微信支付%s"%money)
class Alipay():
    def pay(self,money):
        print("使用支付宝支付%s"%money)

class Applepay():
    def fuqian(self,money):
        print("使用苹果支付了%s"%money)

def Pay(pay_obj,money):
    pay_obj.pay(money)

wechat=Wechat()
# wechat.pay(100)
alipay=Alipay()
# alipay.pay(200)
Pay(wechat,100)
Pay(alipay,200)

applepay=Applepay()
Pay(applepay,300)

运行结果:

针对上面这种情况,其实还可以这样操作:

class Payment():  # 可以让后续写的支付类都需继承这个Payment,当子类去调用pay方法时,如果有的子类中没有实现pay方法(比如Applepay)
    def pay(self,money):  # 当然会来调用父类Payment中的方pay方法,此时就会主动抛一个异常 NotImplemented 表明子类中没有该方法
        raise NotImplemented  # 主动抛出异常
class Wechat(Payment):
    def pay(self,money):
        print("使用微信支付%s"%money)
class Alipay(Payment):
    def pay(self,money):
        print("使用支付宝支付%s"%money)

class Applepay(Payment):
    def fuqian(self,money):
        print("使用苹果支付了%s"%money)

def Pay(pay_obj,money):
    pay_obj.pay(money)

wechat=Wechat()
# wechat.pay(100)
alipay=Alipay()
# alipay.pay(200)
Pay(wechat,100)
Pay(alipay,200)

applepay=Applepay()
Pay(applepay,300)

运行结果:

但是这两种方法,都是必须得去调用Pay(pay_obj,money)方法才行,其实还可以有一种更规范的写法,当实现好一个类时就能发现:

from abc import abstractmethod,ABCMeta
class Payment(metaclass=ABCMeta):  # 必须指定元类
    @abstractmethod  # 必须在pay()方法加一个装饰器
    def pay(self,money):
        pass

# class Payment():  # 可以让后续写的支付类都需继承这个Payment,当子类去调用pay方法时,如果有的子类中没有实现pay方法(比如Applepay)
#     def pay(self,money):  # 当然会来调用父类Payment中的方pay方法,此时就会主动抛一个异常 NotImplemented 表明子类中没有该方法
#         raise NotImplemented  # 主动抛出异常
class Wechat(Payment):
    def pay(self,money):
        print("使用微信支付%s"%money)
class Alipay(Payment):
    def pay(self,money):
        print("使用支付宝支付%s"%money)

class Applepay(Payment):
    def fuqian(self,money):
        print("使用苹果支付了%s"%money)

def Pay(pay_obj,money):
    pay_obj.pay(money)

wechat=Wechat()
# wechat.pay(100)
alipay=Alipay()
# alipay.pay(200)
# Pay(wechat,100)
# Pay(alipay,200)
applepay=Applepay()
# Pay(applepay,300)

运行结果:

这样只需实例化对象 然后把Pay的功能封装一下,写一个Payment的父类,必须指定元类,以及需要实现在子类共有的需要封装的方法pay()方法,但是需要在该方法之前加上abstractmethod装饰器

这样就实现了子类的规范化~

talk is cheap,show me the code
原文地址:https://www.cnblogs.com/xuanxuanlove/p/9679222.html