zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    理解AI的角度
    如何提升分享信息的价值
    大数据和你想的不一样
    《卓有成效的程序员》笔记
    Mac下安装和使用GunPG(GPG)
    hive界面工具SQL Developer的安装;使用sql developer连接hive;使用sql developer连接mysql
    mac os安装jdk、卸载
    前端模板inspinia
    squirrelsql安装
    GOPATH设置
  • 原文地址:https://www.cnblogs.com/xuanxuanlove/p/9679222.html
Copyright © 2011-2022 走看看