zoukankan      html  css  js  c++  java
  • 继承进阶

    1.归一化设计(接口类)

    class AliPay:
        def __init__(self,name):
            self.name = name
        def pay(self,money):
            # 支付宝提供了一个网络上的联系渠道
            print('%s通过支付宝消费了%s元'%(self.name,money))
    
    class WeChatPay:
        def __init__(self,name):
            self.name = name
        def pay(self,money):
            # 微信提供了一个网络上的联系渠道
            print('%s通过微信消费了%s元'%(self.name,money))
    
    # 归一化设计 : 从原来的面向对象编程 -->面向函数编程.降低了用户的使用成本
    def pay_func(person,money):  #支付函数,总体负责支付
        person.pay(money)     #对应支付和对象要支付的金额
    
    alex=AliPay("alex")
    nezha=WeChatPay("nezha")

    #alex.pay(200) #归一化设计,使用当前pay-func函数就不需要
    #nezha.pay(100) #自己用对象去调用pay方法了,就像使用函数直接用
    pay_func(alex,200)     #pay-func传一个alex,传一个200就完事了
    pay_func(nezha,100)
    第二种写法归一化:
    def pay_func(person,payway,money): #
    if payway=="alipay":
    per = AliPay(person)
    elif payway=="wechatpay":
    per=WeChatPay(person)
    per.pay(money)

    pay_func("alex","alipay",200)
    pay_func("nazha","wechatpay",100)
    #接口初成:手动报异常:NotImplementedError来解决开发中遇到的问题
     

    抽象类

    抽象类的特点:
             必须在类定义的时候指定metaclass = ABCMeta
             必须在要约束的方法上方加上@abstractmethod方法

    # 支付途径
    
    # 支付宝 微信 银行卡 nfc支付   #import abc #利用abc模块实现抽象类
    from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta):      # metaclass 元类  metaclass = ABCMeta表示Payment类是一个规范类
        @abstractmethod   #(定义抽象方)     # @abstractmethod表示下面一行中的pay方法是一个必须在子类中实现的方法
        def pay(self):pass #子类必须定义支付功能 # 规定:Payment 就是一个规范类,这个类存在的意义不在于实现实际的功能,而是为了约束所有的子类必须实现pay的方法
                           
          @abstractmethod def back(self):pass #子类必须定义退款功能 # Payment : 抽象类                        # pay = Payment() # 抽象类: 不能实例化 class AliPay(Payment):          # 抽象类主要就是作为基类/父类,来约束子类中必须实现的某些方法 def __init__(self,name):        self.name = name def pay(self,money): # 支付宝提供了一个网络上的联系渠道 print('%s通过支付宝消费了%s元'%(self.name,money)) class WeChatPay(Payment): def __init__(self,name): self.name = name def pay(self,money): # 微信提供了一个网络上的联系渠道 print('%s通过微信消费了%s元'%(self.name,money)) class ApplePay(Payment): def __init__(self,name): self.name = name def pay(self,money): print('%s通过苹果支付消费了%s元'%(self.name,money)) def back(self): print('退款')
    # 归一化设计 : 从原来的面向对象编程 -->面向函数编程.降低了用户的使用成本 def pay_func(person,payway,money): if payway == 'alipay': per = AliPay(person) elif payway == 'wechatpay': per = WeChatPay(person) elif payway == 'ApplePay': per = ApplePay(person) per.pay(money) pay_func('alex','alipay',200) pay_func('nazha','wechatpay',100) pay_func('宝元','ApplePay',100) bao = ApplePay('baoyuan')

    接口 

    1. java 不支持多继承
        python 支持多继承 :通过抽象类的多继承来实现复杂的规范 

    2.python
        抽象类 : 抽象类中的方法可以写一些具体的py代码(规范)
         单继承:都是定义规范的
         多继承:都是定义规范的
    3. java:
      不支持多继承,新的概念 接口 Interface
       和抽象类几乎一模一样的功能 :
            只定义一个接口名字(基类名),内部定义子类必须实现的方法
            接口支持多继承
            接口内部的所有方法都不能写具体的代码,只能用pass代替
    4.抽象类  :
          单继承的形容,并且在单继承中可以在方法中写python代码
     5.接口类  :  更接近java中的接口的概念
           python中由于有了抽象类的多继承,不需要接口的概念了
           一个基类写出来被子类多继承了 : 接口类
           并且在方法中只写pass(你可以选择性的满足)

    借用abc模块来实现接口

    # 动物园
    # 天鹅 : 飞 走 游泳
    # 老虎 : 走 游泳
    # 鹦鹉 : 飞 走 说话
    from abc import ABCMeta,abstractmethod #引入模块
    class Fly_Animal(metaclass=ABCMeta): @abstractmethod def fly(self): print('爷会飞')
    class Swim_Animal(metaclass=ABCMeta): @abstractmethod def swim(self): pass
    class Walk_Animal(metaclass=ABCMeta): @abstractmethod def walk(self): pass class Swan(Fly_Animal,Swim_Animal,Walk_Animal): def fly(self): super().fly() print('飞') def walk(self):print('走') def swim(self):print('游') class Tiger(Walk_Animal,Swim_Animal): def walk(self):print('走') def swim(self):print('游') class Parrot(Fly_Animal,Walk_Animal): def fly(self):print('飞') def walk(self):print('走') def talk(self):print('说') # 不同动物的相同行为是不能混为一谈 # 不同动物的相同行为的方法名字是必须一样

    python2:两种类   经典类  新式类

        经典类,经典类在基础的根如果什么都不写,表示继承xxx

           在经典类中采用的是深度优先 遍历方案. 什么是深度优先. 就是一条路走到头. 然后再回来. 继续找下⼀一个

    1.当类是经典类时,多继承情况下,会按照深度优先方式查找,没有MRO提示你顺序,没有super

    2.当类是新式类时,需要主动继承object,多继承情况下,会按照广度优先方式查找

    python3:只有一种类  新式类

          新式类: 默认继承object类 # object 是所有类的父类

           为什么可以不写__init__?

                  所有object中的类都是你自己不写也可以调用的

            在python3中 所有的类都是新式类,所有的新式类的继承顺序都遵循C3算法,
              可以使用类名.__mro__()这个方法来查看这个继承顺序  

    区别:python3.x和python2.x中的新式类有什么区别?

          1,不需要主动继承object

          2python3中的super()可以直接用,python2中使用必须传参数super(子类名,对象名).方法名

    class A(object):
        def test(self):
            print('from A')
    
    class B(A):
        def test(self):
            print('from B')
    
    class C(A):
        def test(self):
            print('from C')
    
    class D(B):
        def test(self):
            print('from D')
    
    class E(C):
        def test(self):
            print('from E')
    
    class F(D,E):
        # def test(self):
        #     print('from F')
        pass
    f1=F()
    f1.test()
    print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
    
    #新式类继承顺序:F->D->B->E->C->A
    #经典类继承顺序:F->D->B->A->E->C
    #python3中统一都是新式类
    #pyhon2中才分新式类与经典类

     C3算法 - 钻石模型
        每一个类的继承顺醋都是从基类向子类看
        形成一个指向关系的顺序[当前类]+[父类的继承顺序]
        进行一个提取
        如果一个类出现在从左到右的第一个顺序上
        并且没有出现在后面顺序中
        或者出现在后面的顺序中了但是仍然是第一个,
        那么就把这个类提取出来

      

    继承小结 

    继承原理:

     python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列     表,这个MRO列表就是一个简单的所有基类的线性顺序列表

    (为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
    而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
    1.子类会先于父类被检查
    2.多个父类会根据它们在列表中的顺序被检查
    3.如果对下一个类存在两个合法的选择,选择第一个父类)

    继承的作用:

        减少代码的重用
        提高代码可读性
        规范编程模式

    几个名词:

        抽象:抽象即抽取类似或者说比较像的部分。是一个从具题到抽象的过程。
        继承:子类继承了父类的方法和属性
        派生:子类在父类方法和属性的基础上产生了新的方法和属性

    抽象类与接口类:

        1.多继承问题
        在继承抽象类的过程中,我们应该尽量避免多继承;
        而在继承接口的时候,我们反而鼓励你来多继承接口

        2.方法的实现
        在抽象类中,我们可以对一些抽象方法做出基础实现;
        而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现

    super是什么鬼

    super()可以帮我们执行MRO中下一个父类的方法. 通常super()有两个使⽤的地方:

        1. 可以访问父类的构造⽅方法

        2. 当子类方法想调用父类(MRO)中的方法

  • 相关阅读:
    Servlet会话管理一(URL重写和表单隐藏域)
    Eclipse自动补全设置
    String类为什么设计成不可变的
    部署描述符(web.xml)和标注(annotation)
    html中   和空格的区别
    HTML的基本知识点
    Eclipse中配置Tomcat服务器并创建标准Web目录
    Sevlet处理HTML表单
    Servlet API
    Servlet开发的三种方法
  • 原文地址:https://www.cnblogs.com/baoshuang0205/p/10004879.html
Copyright © 2011-2022 走看看