zoukankan      html  css  js  c++  java
  • 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.方法的实现
    在抽象类中,我们可以对一些抽象方法做出基础实现;
    而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
    """
  • 相关阅读:
    x64 平台开发 Mapxtreme 编译错误
    hdu 4305 Lightning
    Ural 1627 Join(生成树计数)
    poj 2104 Kth Number(可持久化线段树)
    ural 1651 Shortest Subchain
    hdu 4351 Digital root
    hdu 3221 Bruteforce Algorithm
    poj 2892 Tunnel Warfare (Splay Tree instead of Segment Tree)
    hdu 4031 Attack(BIT)
    LightOJ 1277 Looking for a Subsequence
  • 原文地址:https://www.cnblogs.com/jinan1/p/10757875.html
Copyright © 2011-2022 走看看