python之面向对象封装,多态

面向对象之封装,多态

  1. 封装

    • 定义:将内容封装在某个地方,以后再去调用被封装在某处的内容

    • 第一步:将内容封装到某处

      class A:
          def __init__(self,name,age):	# 称为构造方法,根据类创建对象时自动执行
              self.name = name
              self.age = age
      obj1 = A('铁憨憨',18) # 将铁憨憨和18分别封装到obj1及self的name和age属性中
      obj2 = A('皮皮寒',16) # 将皮皮寒和16分别封装到obj1及self的name和age属性中
      
    • 第二步:从某处调用被封装的内容

      • 通过对象直接调用

        class A:
            def __init__(self,name,age):
                self.name = name
                self.age = age
        obj1 = A('铁憨憨',18)
        obj2 = A('皮皮寒',16)
        print(obj1.name)
        print(obj2.age)
        
      • 通过self间接调用

        class A:
            def __init__(self,name,age):
                self.name = name
                self.age = age
            def func(self):
                print(self.name)
        obj1 = A('铁憨憨',18)
        obj2 = A('皮皮寒',16)
        obj1.func()
        
  2. 多态

    • 定义:同一个对象多种形态,python默认支持多态

      在java或者c#定义变量或者给函数传值必须定义数据类型,否则就报错。

      类似于python这种弱定义类语言,a可以是任意形态(str,int,object等等)。

    • 鸭子类型

      你看起来像鸭子,那么你就是鸭子。如下代码:

      class A:
          def f1(self):
              print('in A f1')
          def f2(self):
              print('in A f2')
      class B:
          def f1(self):
              print('in A f1')
          def f2(self):
              print('in A f2')
              
      obj = A()
      obj.f1()
      obj.f2()
      
      obj2 = B()
      obj2.f1()
      obj2.f2()
      # A 和 B两个类完全没有耦合性,但是在某种意义上他们却统一了一个标准。
      # 对相同的功能设定了相同的名字,这样方便开发,这两个方法就可以互成为鸭子类型。
      
      # 这样的例子比比皆是:str  tuple list 都有 index方法,这就是统一了规范。
      # str bytes 等等 这就是互称为鸭子类型。
      
  3. super

    super是严格按照类的继承顺序执行的。

    class A:
        def f1(self):
            print('in A')
    
    class Foo(A):
        def f1(self):
            super().f1()
            print('in Foo')
    
    class Bar(A):
        def f1(self):
            print('in Bar')
    
    class Info(Foo,Bar):
        def f1(self):
            super().f1()
            print('in Info f1')
    
    obj = Info()
    obj.f1()
    
    '''
    in Bar
    in Foo
    in Info f1
    '''
    print(Info.mro())  # [<class '__main__.Info'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <class '__main__.A'>, <class 'object'>]
    
    class A:
        def f1(self):
            print('in A')
    
    class Foo(A):
        def f1(self):
            super().f1()
            print('in Foo')
    
    class Bar(A):
        def f1(self):
            print('in Bar')
    
    class Info(Foo,Bar):
        def f1(self):
            super(Foo,self).f1()
            print('in Info f1')
    
    obj = Info()
    obj.f1()
    # in Bar
    # in Info f1
    
  4. 类的约束

    在某些的情况下(在一些重要的逻辑,与用户数据相关等核心部分),我们要建立一种约束,避免发生此类错误.

    • 在父类建立一种约束

      提取父类,然后在父类中定义好方法,在这个⽅法中什么都不用干,就抛⼀个异常就可以了,这样所有的子类都必须重写这个方法,否则,访问的时候就会报错。

      class Payment:
          """
          此类什么都不做,就是制定一个标准,谁继承我,必须定义我里面的方法。
          """
          def pay(self,money):
              raise Exception('子类必须定义此方法')
      class Alipay(Payment):
          def pay(self,money):
              print(f'利用支付宝支付了{money}')
      class QQpay(Payment):
          def pay(self,money):
              print(f'利用qq支付了{money}')
      class Wechatpay(Payment):
          def fuqian(self,money):
              print(f'利用微信支付了{money}')
      
      def pay(obj,money):
          obj.pay(money)
      
      obj3 = Wechatpay()
      pay(obj3,100)	# 由于Wechatpay中没有pay方法,会执行Payment中的pay,会弹出错误
      
    • 模拟抽象类(制定一种规范)的概念,建立一种概念

      使用元类来描述父类,在元类中给出一个抽象方法,这样子类就不得不给出抽象方法的具体实现,也可以起到约束效果

      from abc import ABCMeta,abstractmethod
      class Payment(metaclass=ABCMeta):	# # 抽象类 接口类  规范和约束  metaclass指定的是一个元类
          @abstractmethod
          def pay(self,money):	# 抽象方法
              pass
      class Alipay(Payment):
          def pay(self,money):
              print(f'利用支付宝支付了{money}')
      class QQpay(Payment):
          def pay(self,money):
              print(f'利用qq支付了{money}')
      class Wechatpay(Payment):
          def fuqian(self,money):
              print(f'利用微信支付了{money}')
      
      def pay(obj,money):
          obj.pay(money)
      
      obj3 = Wechatpay()	# 在实例化时@abstractmethod会判断obj3中有没有pay方法,如果没有就会报错
      pay(obj3,100)
      
    • 总结:约束就是父类对子类进行约束,子类必须要写xxx方法。

      1. 使用抽象类和抽象方法,由于改方案来源是java和c#,所以使用频率很少
      2. 使用认为抛出异常的方案,并且尽量抛出的是NotlmplementError,这样比较专业,而且错误比较明确。
posted @ 2019-07-10 15:57  小小蚂蚁mm  阅读(75)  评论(0编辑  收藏  举报