zoukankan      html  css  js  c++  java
  • day25:接口类和抽象类

    1,接口类和抽象类知识背景:一开始在程序界是没有这些概念的,后来就流行了一种语言叫做JAVA,JAVA是一种典型的纯面向对象的语言,JAVA写的程序都是非常适用于更庞大的项目,很多程序员就总结出了一些设计程序的方式,比如说,这一个程序要实现的是哪一类的问题,给这些问题归类,实现A问题用一种思路,实现B问题用另外一种思路,于是就出现了设计模式,所以设计模式一开始最早的时候是源自于JAVA,后来过了一段时间,这个设计模式在整个程序界火了起来,他很经典,总结了很多经典的问题,后来出了一本书,小黑皮的,最早的时候,也没有接口的概念,这个接口的概念,来源于设计模式里,在Python里,其实Python是一门很特殊的语言,后面多态的时候会具体讲特殊在哪儿,因为Python很简单,有他的简便性和便捷性,所以大家对于Python要不要设计模式持两种态度,一种认为,设计模式是一种经典的设计思想,另一种认为,既然源自于JAVA,那么他可能更适合于JAVA,不那么适合于Python,所以贬的人贬,推崇的人就很推崇。

    2,抽象类和接口类很多人是分不清楚的,Python原生是不支持接口类的,根本没有这个概念,但是由于设计模式里面有,所以我们就介绍这个概念。Python原生支持抽象类。他俩在Python里本身很接近,其他语言还是有区别的

    3,支付功能

    class Wechat:
        def pay(self,money):
            print('已经用微信支付了%s元'%money)
    
    class Alipay:
        def pay(self,money):
            print('已经用支付宝支付了%s元'%money)
    
    weChat = Wechat()
    
    weChat.pay(100)
    ali = Alipay()
    ali.pay(200)
    
    # 统一支付入口,类似于len函数对比
    def pay(pay_obj,money):
        pay_obj.pay(money)
    
    pay(weChat,100)
    pay(ali,200)

    4,添加一个Applepay

    # 这样添加的支付方式没有办法统一了
    class Applepay:
        def fuqian(self,money):
            print('已经用Applepay支付了%s'%money)

    5,这个地方调用的时候会报错

    class Payment:
        def pay(self,money):
            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('已经用Applepay支付了%s'%money)
    
    weChat = Wechat()
    
    weChat.pay(100)
    ali = Alipay()
    ali.pay(200)
    apple = Applepay()
    apple.pay(300) # TypeError: exceptions must derive from BaseException

    6,如何不调用就可以知道这个错误呢?

    from abc import abstractmethod,ABCMeta
    class Payment(metaclass=ABCMeta):  # 元类,所有类都有个机制,默认是type,这个机制,支持创造一个类,
        # 加上这句话,表示我即将要写一个类的规范了。
        #  这一句要求我要实现一个接口类了。
        @abstractmethod
        def pay(self,money):pass
    # 规范,既可以说是抽象类,也可以说是接口类,本身就是一种规范。
    
    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('已经用Applepay支付了%s'%money)
    
    apple = Applepay()

    7,接口类,默认多继承,接口类中的所有的方法都必须不能实现,这个规定是来自于JAVA的,但是如果说在Python里面硬要实现,也是可以的,只不过一般情况下我们不建议写

    8,抽象类,不支持多继承,尽量只用单继承,抽象类中可以实现一些方法,里面可以有一些代码的实现。两者共同点,就是要规范子类,Python里面区别不大。一个单继承,一个多继承

    9,类是从一堆对象中抽取相同的内容,抽象类是从一堆类中抽取相同的内容,包括数据属性和函数属性。抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。

    10,接口类的多继承和接口隔离原则,想象之前的开放封闭原则,这个例子更类似于接口类,面向对象的方法。

    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):pass
    class Eagle(Fly_Animal,Walk_Animal):pass
    class Swan(Swim_Animal,Walk_Animal,Fly_Animal):pass
    
    # 接口类,
    # 接口隔离原则,编程时的一个原则,使用多个专门的接口,而不是单一的总接口,即客户端不应该依赖于哪些不需要的接口

    11,接口的思想就是,我要实现不同的功能,我就去继承不同的接口来规范我当前的类里面需要有哪些函数。接口类其实没有的话,也能实现功能,只不过不规范。

    12,抽象类的单继承

    13,

    # Python里面一切都是对象,操作系统里面一切都是文件
    import 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() #报错,子类没有定义抽象方法
    # TypeError: Can't instantiate abstract class Txt with abstract methods read, write
    
    class Txt(All_file): # 子类继承抽象类,但是必须定义read和write方法
        def read(self):print('txt read')
        def write(self):print('txt write')
    
    class Sata(All_file):
        def read(self):print('sata read')
        def write(self):print('sata write')
    
    class Process(All_file):
        def read(self):print('process read')
        def write(self):print('process write')
    
    wenjianjia = Txt()
    yingpan = Sata()
    jincheng = Process()
    
    # 这样大家都被归一化了,也就是一切皆文件的思想
    wenjianjia.read()
    yingpan.write()
    jincheng.read()
    
    # 一般情况下 单继承 能实现的功能都是一样的,所以在父类中可以有一些简单的基础实现
    # 多继承的情况,由于功能比较复杂,所以不容易抽象出相同的功能的具体实现写在父类中
    # 接口类还是抽象类,面向对象的开发规范
    # Python中没有接口类,Java里有接口interface这个概念
    # Python自带多继承,所以我们直接用class来实现接口类
    # Python中支持抽象类:一般情况下 单继承 不能实例化 且可以实现python代码

    14,JAVA里的所有类的继承都是单继承,所以抽象类玩么的解决了单继承需求中的规范问题,但是对于多继承的需求,由于JAVA本身语法的不支持,所以创建了接口Interface这个概念来解决多继承的问题。

    15,Python天生支持多态,多态,一类事务的多种形态(广义的多态)向不同的对象发送同一个消息,会有不同的响应。相同的方法,不同对象做的事不同,就叫做多态,JAVA里面想要实现多态,必须有一个共同的父类,才可实现不同的对象调用同样的方法,传的对象类型,Python里面是不需要的,所以这个共同的父类是不需要的,天生支持多态。

    16,Python是一门动态强类型的语言,不能直接说强类型,也不能说是弱类型的,弱类型支持 2+‘str'

    17,Python里面不崇尚多态,不需要借助父类来实现多态。Python崇尚鸭子类型,鸭子类型,补充上根据继承得来的相似,我只是自己实现我自己的代码就可以了,如果两个类刚好相似,并不产生父类的子类的兄弟关系,而是鸭子类型。这种相似是自己写代码约束的,而不是通过父类约束的,优点:松耦合,每个相似的类之间都没有影响,缺点:太随意了,没有硬性的规范,去必须实现这个功能。只能靠自觉。

    18,强类型语言,只能用多态,Python不用实现共同的父类,崇尚鸭子类型。

    19,封装

    # 广义上面向对象的封装:代码的保护,面向对象思想的本身就是一种
    # 只让自己的对象能调用自己类中的方法
    
    # 狭义上的封装 ---面向对象的三大特征之一
    # 属性和方法都隐藏起来 不让你看见
    
    class Person:
        def __init__(self,name,passwd,id):
            self.name = name
            self.passwd = passwd
            self.__id = id
    
    alex = Person('alex','alex3714',12)
    print(alex.passwd)  # alex3714
    print(alex.__id) # AttributeError: 'Person' object has no attribute '__id'

    20,前面加上双下划线,就变成私有属性了,

    class Person:
        def __init__(self,name,passwd,id):
            self.name = name
            self.passwd = passwd
            self.__id = id
    
        def get_id(self):
            return self.__id
    
    alex = Person('alex','alex3714',12)
    print(alex.passwd)  # alex3714
    # print(alex.__id) # AttributeError: 'Person' object has no attribute '__id'
    
    print(alex.__dict__)  # {'name': 'alex', 'passwd': 'alex3714', '_Person__id': 12}
    print(Person.__dict__)
    print(alex._Person__id) # 12  _类名_属性名,实际中不可以这样用,这是一种投机倒把的方式

    21,

    alex.__id = 10  # 这样写只是给对象新添加了一个属性
    print(alex.passwd)
    print(alex.__dict__)  # {'name': 'alex', 'passwd': 'alex3714', '_Person__id': 12, '__id': 10}
    print(Person.__dict__)

    22,总结:所有的私有 都是在变量的左边加上双下划线:对象的私有属性,类中的私有方法,类中的静态私有属性。所有的私有的都不能在类的外部使用。

    23,其他语言中有public,protected,private,Python中没有protected,只有public和private,python 里的私有都是假的,只不过是包了一层而已。只要在类的内部使用私有属性,就会自动的带上类名

    24,

    class Person:
      __key = 123 # 类的私有属性
    def __init__(self,name,passwd,id): self.name = name self.passwd = passwd self.__id = id # 私有属性 def __get_id(self): # 私有方法 return self.__id def login(self): # 只可以在类的内部使用私有变量 self.__get_id()
  • 相关阅读:
    getopt for windows
    开源代码学习之Tinyhttpd
    GCC 中的编译器堆栈保护技术
    读《程序员的思维修炼》有感
    main之前初始化流程
    平均速度
    显示图案
    圆的面积和周长
    C#(Winform) Http 发送数据
    Android BaseAdapter的使用
  • 原文地址:https://www.cnblogs.com/lisa-blog/p/10236055.html
Copyright © 2011-2022 走看看