• 023_接口类,抽象类,多态,鸭子类型,封装


    1,接口类
    class Wechat():
        def pay(self,money):
            print('已经用微信支付了%s元'%money)
    class Alipay():
        def pay(self,money):
            print('已经用支付宝支付了%s元' % money)
    wechat = Wechat()
    ali = Alipay()
    # wechat.pay(100)
    # ali.pay(200)
    #将上面两句用下面的替换,
    def pay(pay_obj,money):  # 统一支付入口
        pay_obj.pay(money)
    pay(wechat,100)
    pay(ali,200)

    2,规范化程序

    2.1,问题
      如果来个人接手这个程序,他要添加一个应用支付。但他并不知道你的其它应用支付方法你定义的都是pay方法(程序如上例),且统一支付接口调用pay方法。
      他自己添加的应用支付的支付方法并不是用pay命名的。因此,当用统一接口支付时,找不到对应的支付方法,就会报错。
      例如在上程序添加如下代码
    class Applepay():
        def zhifu(self,money):
            print('已经用applepay支付了%s元' % money)
    app = Applepay()
    pay(app,100) #报错
      2.2,解决上问题,
      定义一个父类,并将上面的支付程序都继承这个父类,当用统一接口调用时,如该应用的支付没有该方法,就会执行父类的这个pay方法,抛出异常给接受该程序的人看,告诉他,没有实现这个方法。
    class Payment:
    	def pay(self,money):
    		raise NotImplementedError	#抛出没有实现这个方法的异常
    
    class Applepay(Payment):
    	def zhifu(self,money):
    		print('已经用applepay支付了%s元' % money)
    
    def pay(pay_obj,money):  # 统一支付入口
    	pay_obj.pay(money)
    	
    app = Applepay()
    pay(app,100)	#报错
      2.3,解决方法升级,规范化程序
    from abc import abstractmethod,ABCMeta
    class Payment(metaclass=ABCMeta):       # 元类 默认的元类 type   #metaclass不是继承,而是指定元类
        @abstractmethod
        def pay(self,money):pass                # 没有实现这个方法
        通过上面的代码,写一个规范程序的父类。将各支付类都继承该父类。起到规范子类程序的作用。
        这样接手的人在实例化对象时,就会报错,并提示少了什么方法。
    app = Applepay()  #报错
    3,抽象类与接口类
                  # python中规范化程序称为 :接口类或者抽象类都可以
        #在Java中有严格区分:
        # 接口类 支持多继承,接口类中的所有的方法都必须不能实现 —— java
        # 抽象类 不支持多继承,抽象类中方法可以有一些代码的实现 —— java

      抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。

      抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计 

      在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念。

     
    4,多态
        python没有多态,因为python天生支持多态
        多态指的是一类事物有多种形态,动物有多种形态:人,狗,猪
    import abc
    class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
        @abc.abstractmethod
        def talk(self):
            pass
    class People(Animal): #动物的形态之一:人
        def talk(self):
            print('say hello')
    class Dog(Animal): #动物的形态之二:狗
        def talk(self):
            print('say wangwang')
    class Pig(Animal): #动物的形态之三:猪
        def talk(self):
            print('say aoao')
    5,鸭子类型
      逗比时刻:
    • Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’ 。
    • python程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象,也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度。
    • 例1:利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法
    • 例2:序列类型有多种形态:字符串,列表,元组,但他们直接没有直接的继承关系
      #二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
    class TxtFile:
        def read(self):
            pass
        def write(self):
            pass
    class DiskFile: def read(self): pass def write(self): pass
    6,封装
      6.1,封装的方式
        # 广义上面向对象的封装 :代码的保护,面向对象的思想本身就是一种
        # 只让自己的对象能调用自己类中的方法
      # 狭义上的封装 —— 面向对象的三大特性之一
      # 属性 和 方法都藏起来 不让你看见
        # 所有的私有 都是在变量的左边加上双下划綫
                # 对象的私有属性
                # 类中的私有方法
               # 类中的静态私有属性
        # 所有的私有的 都不能在类的外部使用
        #在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。
    class Person:
        __key = 123  # 私有静态属性
        def __init__(self,name,passwd):
            self.name = name
            self.__passwd = passwd   
    		# 在变量的左边加上双下划线,就变成私有属性  #变形为:_Person__passwd
        def __get_pwd(self):	# 私有方法   #变形为:_Person__get_pwd
            return self.__passwd   #只要在类的内部使用私有属性,就会自动的带上“_类名”,在外部这样定义不会。
        def login(self):          # 正常的方法调用私有的方法,即只在内部使用
            self.__get_pwd()
    alex = Person('alex','alex3714')
    print(alex._Person__passwd)   # “_类名或对象名__属性名”可以调出该属性,但是不要用此方法在外部操作。
    # print(alex.get_pwd()) #不可调用

      6.2,可以设置,get和set方法以便在外部更改查看私有属性,可能会想为什么要多此一举,不设成私有的不久行了吗。

        这样写有它的好处,即可以在get和set方法中加限定条件,以满足要求。所以,如果不需要对外限定保护属性,可以不用设定成私有的。

     
    class Room:
        def __init__(self,name,length,width):
            self.__name = name
            self.__length = length
            self.__width = width
        def get_name(self):       #不加限定条件的get
            return self.__name
        def set_name(self,newName):  #加限定条件的set
            if type(newName) is str and newName.isdigit() == False:
                self.__name = newName
            else:
                print('不合法的姓名')
        def area(self):
            return self.__length * self.__width
    
    jin = Room('金老板',2,1)
    print(jin.area())
    jin.set_name('2')
    print(jin.get_name())
    

      6.3,假设父类的私有属性 能被子类调用么?,不会

    class Foo:
        __key = '123'       #变形为: _Foo__key
    
    class Son(Foo):
        print(Foo.__key)     #继承属性后变形为: _Son__key
    

      6.4,会用到私有的这个概念de场景
        1.隐藏起一个属性 不想让类的外部调用
        2.我想保护这个属性,不想让属性随意被改变
        3.我想保护这个属性,不被子类继承

     
  • 相关阅读:
    Symfony框架实战学习
    学习Symfony之环境的搭建
    js的学习 (数组)
    js的学习 (对象)
    js的学习 (语句)
    Django 应用开发(3)
    Django 应用开发(2)
    Django 学习搭建博客
    2-4.通用选择器
    2-3.class选择器
  • 原文地址:https://www.cnblogs.com/eternity-twinkle/p/10605583.html
Copyright © 2020-2023  润新知