zoukankan      html  css  js  c++  java
  • Python学习笔记25:接口类、抽象类和封装

    接口类、抽象类和封装都是和类相关的一些知识概念。

    接口类

    在说明什么是接口类之前我们先来引入一个问题,见下

    # 假设我们定义了两种支付方式,分别为支付宝和微信,
    class
    Alipay: ''' 支付宝支付 ''' def pay(self,money): print('支付宝支付了%s元'%money) class Applepay: ''' apple pay支付 ''' def pay(self,money): print('apple pay支付了%s元'%money) ali = Alipay()
    print(ali.pay(100)) apy = Applepay()
    print(apy.pay(100))

    # 一般情况下,为了调用方便,我们一般会统一一个支付调用的方式,上面的调用虽然可以解决问题,但是不方便

    def pay(payment,money):
        '''
        支付函数,总体负责支付
        对应支付的对象和要支付的金额
        '''
        payment.pay(money)

    p = Alipay()
    pay(p,200)

    # 但是当我们又有新的支付方式进来,而且这些新的支付方式不是同一个人开发的,在不知道类中的函数名字都是pay命名的时候
    # 就容易出错,如下面这样:
    class Alipay:
        '''
        支付宝支付
        '''
        def pay(self,money):
            print('支付宝支付了%s元'%money)
    
    class Applepay:
        '''
        apple pay支付
        '''
        def pay(self,money):
            print('apple pay支付了%s元'%money)
    
    class Wechatpay:
        def fuqian(self,money):
            '''
            实现了pay的功能,但是名字不一样
            '''
            print('微信支付了%s元'%money)
    
    def pay(payment,money):
        '''
        支付函数,总体负责支付
        对应支付的对象和要支付的金额
        '''
        payment.pay(money)
    
    
    p = Wechatpay()
    pay(p,200)   #此时执行pay函数就会报错,因为Wechatpay类中的函数不是以pay命名的,且这种报错不好分析

    为了解决这种问题,可以自己主动设置一个报错机制,定义一个父类

    # 接口初成:手动报异常:NotImplementedError来解决开发中遇到的问题
    class
    Payment: def pay(self): raise NotImplementedError class Wechatpay(Payment): # 这里继承了Payment这个类 def fuqian(self,money): print('微信支付了%s元'%money) p = Wechatpay() #这里不报错 pay(p,200) #这里报错了

    可以在继续优化,写成下面这种形式,借用abc模块来实现接口

    from abc import abstractmethod,ABCMeta
    class Payment(metaclass=ABCMeta):  # 元类 默认的元类 type,说明要写一个规范类
        @abstractmethod  # 装饰器,作用就是来实现一个规范类,用来规范子类
        def pay(self,money):pass   # 没有实现这个方法
    
    class Wechatpay(Payment):
        def fuqian(self,money): # 这里修改成pay(self,money)就不会报错了
            print('微信支付了%s元'%money)
    
    p = Wechatpay() #不调就报错了,这样在执行这里的就是就报错了,会告诉哪里出错

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

    继承的第二种含义非常重要。它又叫“接口继承”。
    接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。

    内容参考:https://www.cnblogs.com/Eva-J/articles/7293890.html

    接口提取了一群类共同的函数,可以把接口当做一个函数的集合。
    
    然后让子类去实现接口中的函数。
    
    这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。
    
    归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。
    
    比如:我们定义一个动物接口,接口里定义了有跑、吃、呼吸等接口函数,这样老鼠的类去实现了该接口,松鼠的类也去实现了该接口,由二者分别产生一只老鼠和一只松鼠送到你面前,即便是你分别不到底哪只是什么鼠你肯定知道他俩都会跑,都会吃,都能呼吸。
    
    再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样
    # tiger 走路 游泳
    # swan 走路 游泳 飞
    # oldying 走路 飞
    from abc import abstractmethod,ABCMeta
    class Swim_Animal(metaclass=ABCMeta):
        @abstractmethod
        def swim(self):pass # 此处的函数只是一个规范,不执行
    
    class Walk_Animal(metaclass=ABCMeta):
        @abstractmethod
        def walk(self):pass
    
    class Fly_Animal(metaclass=ABCMeta):
        @abstractmethod
        def fly(self):pass
    
    class Tiger(Walk_Animal,Swim_Animal):  # 这里下面必须要写上上面继承规范类里面的功能
        def walk(self):
            pass
        def swim(self):
            pass
    class OldYing(Fly_Animal,Walk_Animal):pass
    class Swan(Swim_Animal,Walk_Animal,Fly_Animal):pass
    
    # 接口类  刚好满足接口隔离原则 面向对象开发的思想 规范,功能应该要隔离开来,需要哪个功能继承哪个功能

    抽像类

    import abc #利用abc模块实现抽象类
    
    class All_file(metaclass=abc.ABCMeta):
        all_type='file'
        @abc.abstractmethod #定义抽象方法,无需实现功能
        def read(self):
            '子类必须定义读功能'
            with open('filaname') as f:
                pass
    
        @abc.abstractmethod #定义抽象方法,无需实现功能
        def write(self):
            '子类必须定义写功能'
            pass
    
    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来实现了接口类,模拟了Java的接口的概念。
    # python中支持抽象类  : 一般情况下 单继承  不能实例化,因为它是用来抽象出来一个共同的功能
      #  且可以实现python代码

    封装

    # 广义上面向对象的封装 :代码的保护,面向对象的思想本身就是一种
    # 只让自己的对象能调用自己类中的方法
    
    # 狭义上的封装 —— 面向对象的三大特性之一
    # 属性 和 方法都藏起来 不让你看见
    class Person:
        __key = 123  # 私有静态属性
        def __init__(self,name,passwd):
            self.name = name
            self.__passwd = passwd   # 私有属性,双下划线,不想让别人调出来看见,只是代码保护,并不是保护数据的机制
    
        def __get_pwd(self):         # 私有方法
            return self.__passwd   #只要在类的内部使用私有属性,就会自动的带上_类名,且只有在内部才有私有属性和方法
    
        def login(self):          # 正常的方法调用私有的方法
            self.__get_pwd()
    
    alex = Person('alex','alex3714')
    print(alex._Person__passwd)   # _类名__属性名
    print(alex.get_pwd())
    
    # 所有的私有 都是在变量的左边加上双下划綫
        # 对象的私有属性
        # 类中的私有方法
        # 类中的静态私有属性
    # 所有的私有的 都不能在类的外部使用
  • 相关阅读:
    繁忙的都市 最小生成树 入门题
    洛谷P2801 教主的魔法 分块
    洛谷 P3203 [HNOI2010]弹飞绵羊 分块
    洛谷P2607 [ZJOI2008]骑士 基环树动归
    Hdu 2586 树链剖分求LCA
    洛谷 P3384 【模板】树链剖分
    洛谷P1816 忠诚 分块
    最全前端开发面试问题及答案整理
    CSS垂直居中和水平居中
    实现一个图片懒加载插件有多难?
  • 原文地址:https://www.cnblogs.com/zheng1076/p/11091171.html
Copyright © 2011-2022 走看看