• Python--抽象类接口类


    一、

    继承有两种用途:
    """
     一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
     二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)
     且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
     三、接口隔离原则:使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口
    """
    """
    接口类:基于同一个接口实现的类  刚好满足接口隔离原则 面向对象开发的思想 规范
    接口类,python 原生不支持  在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念
    """

     一、接口类单继承

    我们来看一段代码去了解为什么需要接口类

    class Alipay:
        def pay(self,money):
            print('支付宝支付了')
    class Apppay:
        def pay(self,money):
            print('苹果支付了')
    class Weicht:
        def pay(self,money):
            print('微信支付了')
    def pay(payment,money):       # 支付函数,总体负责支付,对应支付的对象和要支付的金额
        payment.pay(money)
    p=Alipay()
    pay(p,200)      #支付宝支付了
    这段代码,实现了一个有趣的功能,就是通过一个总体的支付函数,实现了不同种类的支付方式,不同是支付方式作为对象,传入函数中
    但是开发中容易出现一些问题,那就是类中的函数名不一致,就会导致调用的时候找不到类中对应方法,例题如下:
    class Alipay:
        def paying(self,money):    #这里类的方法可能由于程序员的疏忽,写的不是一致的pay,导致后面调用的时候找不到pay
            print('支付宝支付了')
    class Apppay:
        def pay(self,money):
            print('苹果支付了')
    class Weicht:
        def pay(self,money):
            print('微信支付了')
    def pay(payment,money):       # 支付函数,总体负责支付,对应支付的对象和要支付的金额
        payment.pay(money)
    p=Alipay()   #不报错
    pay(p,200)      #调用执行就会报错,'Alipay' object has no attribute 'pay'
    这时候怎么办呢?可以手动抛异常:NotImplementedError来解决开发中遇到的问题
    class payment:
        def pay(self):
            raise NotImplementedError    #手动抛异常
    class Alipay:
        def paying(self, money):  # 这里类的方法不是一致的pay,导致后面调用的时候找不到pay
            print('支付宝支付了')
    def pay(payment, money):  # 支付函数,总体负责支付,对应支付的对象和要支付的金额
        payment.pay(money)
    
    p = Alipay()  # 不报错
    pay(p, 200)  #调用的时候才会报错  'Alipay' object has no attribute 'pay'
    也可以借用abc模块来处理这种错误
    from abc import abstractmethod, ABCMeta     #接口类中定义了一些接口名:Pay,且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
    class Payment(metaclass=ABCMeta):    #抽象出的共同功能Pay
        @abstractmethod
        def pay(self,money):pass    #这里面的pay 来源于下面类中的方法pay,意思把这个方法规范为统一的标准,另外建一个规范类Payment
    class Alipay(Payment):
        def paying(self, money):    #这里出现paying和我们规范的pay不一样,那么在实例化 Alipay的时候就会报错
            print('支付宝支付了')
    class Weicht(Payment):
        def pay(self,money):
            print('微信支付了')
    def pay(pay_obj,money):
        pay_obj.pay(money)
    p=Alipay()   #实例化的时候就会报错  Can't instantiate abstract class Alipay with abstract methods pay 之前两个例子都是在执行的时候报错,这里不一样的是实例化就会知道是哪里发生错误了
    """
    总结:用abc模块装饰后,在实例化的时候就会报错,那么当我们代码很长的时候,就可以早一点预知错误,所以以后在接口类类似问题中用这个模块
    接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,
    可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。
    """
     二、接口类多继承
    from abc import abstractmethod,ABCMeta
    class Walk_animal(meteaclass=ABCMeta):
        @abstractmethod
        def walk(self):
            print('walk')
    class Swim_animal(meteaclass=ABCMeta):
        @abstractmethod
        def swim(self):pass
    class Fly_animal(metaclass=ABCMeta)
        @abstractmethod
        def fly(self):pass
    #如果正常一个老虎有跑和跑的方法的话,我们会这么做
    class Tiger:
        def walk(self):pass
        def swim(self):pass
    #但是我们使用接口类多继承的话就简单多了,并且规范了相同功能
    class Tiger(Walk_animal,Swim_animal):pass
    #如果此时再有一个天鹅swan,会飞,走,游泳 那么我们这么做
    class Swan(Walk_animal,Swim_animal, Fly_animal):pass
    # 这就是接口多继承
    三、抽象类
    #抽象类
    # 抽象类的本质还是类,
    # 指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性
    """
    1.抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计
    2.在继承抽象类的过程中,我们应该尽量避免多继承;
    3.而在继承接口的时候,我们反而鼓励你来多继承接口
    # 一般情况下 单继承 能实现的功能都是一样的,所以在父类中可以有一些简单的基础实现
    # 多继承的情况 由于功能比较复杂,所以不容易抽象出相同的功能的具体实现写在父类中
    
    """
    #一切皆文件
    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):
    #     pass
    #
    # t1=Txt() #报错,子类没有定义抽象方法
    
    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()
    
    print(wenbenwenjian.all_type)
    print(yingpanwenjian.all_type)
    print(jinchengwenjian.all_type)

     四、扩展:

    不管是抽象类还是接口类 : 面向对象的开发规范 所有的接口类和抽象类都不能实例化
    java :
    java里的所有类的继承都是单继承,所以抽象类完美的解决了单继承需求中的规范问题
    但对于多继承的需求,由于java本身语法的不支持,所以创建了接口Interface这个概念来解决多继承的规范问题
    python:
    python中没有接口类  :
       python中自带多继承 所以我们直接用class来实现了接口类
    python中支持抽象类  : 一般情况下 单继承  不能实例化
       且可以实现python代码

    五、注意

    """
    1.多继承问题
    在继承抽象类的过程中,我们应该尽量避免多继承;
    而在继承接口的时候,我们反而鼓励你来多继承接口
    
    2.方法的实现
    在抽象类中,我们可以对一些抽象方法做出基础实现;
    而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
    """
  • 相关阅读:
    剑指offer2:替换空格
    题目:求第五个人的年龄
    编写一个函数,输入n为偶数时,调用函数求1/2+1/4+…+1/n,当输入n为奇数时,调用函数1/1+1/3+…+1/n(利用指针函数)
    原创| 输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。
    编程题30 题目:将一个数组逆序输出。
    编程题32 题目:取一个整数a从右端开始的4~7位。
    编程题31 题目:将一个数组逆序输出。
    daisy的词源
    2018年学习日志
    11
  • 原文地址:https://www.cnblogs.com/jinan1/p/10757875.html
Copyright © 2020-2023  润新知