zoukankan      html  css  js  c++  java
  • 初识面向对象二(继承/抽象/C3)

    面向对象中的三大特性(所有语言通用)

    继承

    多态

    封装


    继承的目的:为了解决类与类之间代码重复的问题

    类的继承的语法:
    单继承
    class A:pass
    class B(A):pass
    print(B.__bases__)
    在定义类的时候加(),括号写的类就是继承的类
    B类继承A类
    A类 : 父类 基类 超类
    B类 : 子类 派生类
    多继承(python支持 java不支持)
    class C:pass
    class D:pass
    class E(C,D):pass
    print(E.__bases__)
    E继承C,D
    C,D都是父类
    E是子类
    
    
    使用继承这个概念的过程
    class Animal:
    def __init__(self,name,kind,language):
    self.name = name
    self.kind = kind
    self.language = language
    def eat(self):
    print('%s is eating'%self.name)
    def drink(self):
    print('%s is drinking'%self.name)
    def yell(self):
    print('%s say %s'%(self.name,self.language))
    class Cat(Animal):pass
    class Dog(Animal):pass
    小花 = Cat('小花','金吉拉','喵喵')
    小黑 = Dog('小黑','土狗','旺旺')
    小花.yell()
    小黑.yell()
    print(小花.name)
    print(小花.kind)
    子类可以继承父类的方法和属性
    实例化的执行流程:
    先开辟一块空间,并且空间中已经有了一个类指针,指向Cat
    执行__init__方法,在Cat类的空间中没有init方法,找Animal类中的init
    将空间返回给小花变量
    继承
    子类调用方法,如果子类自己有用自己的,用了自己的就不用父类的了
    如果子类自己没有才调用父类的

    对于有不同的方法
    class Animal:
    def __init__(self,name,kind,language):
    self.name = name
    self.kind = kind
    self.language = language
    def eat(self):
    print('%s is eating'%self.name)
    def drink(self):
    print('%s is drinking'%self.name)
    def yell(self):
    print('%s say %s'%(self.name,self.language))
    class Cat(Animal):
    def climb(self): # 派生方法
    print('%s can climb'%self.name)
    class Dog(Animal): # 派生方法
    def lookafter_door(self):
    print('%s can look after door'%self.name)
    小花 = Cat('小花','金吉拉','喵喵')
    小黑 = Dog('小黑','土狗','旺旺')
    小花.climb()
    小黑.lookafter_door()

    animal_1 = Animal('大金鱼','鱼','吐泡泡')
    animal_1.climb() # 报错

    继承

    子类调用方法,如果子类自己有用自己的,用了自己的就不用父类的了
    如果子类自己没有才调用父类的
    如果子类有个性化的父类没有的方法,可以单独定义在子类中 - 派生方法
    只有子类能够使用父类中的方法,父类不可以使用子类中的方法
    具体的例子:


    class Animal:
    def __init__(self,name,kind,language):
    self.name = name
    self.kind = kind
    self.language = language
    def eat(self):
    print('%s is eating'%self.name)
    def drink(self):
    print('%s is drinking'%self.name)
    def yell(self):
    print('%s say %s'%(self.name,self.language))
    def sleep(self):
    print('%s 在睡觉'%self.name)
    class Cat(Animal):
    def climb(self): # 派生方法
    print('%s can climb'%self.name)
    def sleep(self):
    #1. Animal.sleep(self) # 父类名,主动传self
    #super(self,Cat).sleep() # 过程 super(self,子类名).方法名()
    #2. super().sleep() # super().方法名()
    print('团着睡')
    class Dog(Animal): # 派生方法
    def lookafter_door(self):
    print('%s can look after door'%self.name)

    小花 = Cat('小花','金吉拉','喵喵')
    小花.sleep() # 既希望走父类的基础的sleep,又希望走自己的方法

    当某一个方法,父类和子类都拥有的时候,那么在子类的方法中,调用父类的同名方法
    1.父类名.方法名(self,...)
    2.super().sleep(...)

    
    
    总结:
    继承
    两种语法:
    单继承
    多继承
    几个基础概念
    父类 : 超类 基类
    子类 : 派生类
    为什么要继承 : 几个类之间有重复的属性/方法 ,就把相同的属性和方法抽象出来,作为父类,子类去继承父类
    父类和子类之间的关系 : 子类关联父类,父类并不关联子类
    子类使用父类的方法
    子类中有,父类中没有 : 用子类的
    父类中有,子类中没有 : 用父类的
    子类父类中都有 : 默认情况下用子类的不用父类的
    既想用父类又想用子类 : 父类名.方法名(子类对象),super().方法名()
    子类父类中都没有 : 报错


    抽象类: from abc import ABCMeta,abstractmethod
    举例说明:
    from abc import ABCMeta,abstractmethod
    class Payment(metaclass=ABCMeta):
    @abstractmethod #规定支付功能
    def pay(self):pass

    @abstractmethod #规定退款功能
    def back(self): pass

    class AliPay(Payment):
    def __init__(self,name):
    self.name = name
    def pay(self,money):
    print('%s通过支付宝消费了%s元'%(self.name,money))
    def back(self,tk):
    print('%s通过支付宝退款了%s元'%(self.name,tk))

    class WeChatPay(Payment):
    def __init__(self,name):
    self.name = name
    def pay(self,money):
    print('%s通过微信消费了%s元'%(self.name,money))
    def back(self,tk):
    print('%s通过微信退款%s元'%(self.name,tk))

    class ApplePay(Payment):
    def __init__(self,name):
    self.name = name
    def pay(self,money):
    print('%s通过苹果消费了%s元'%(self.name,money))
    def back(self,tk):
    print('%s通过苹果退款%s元'%(self.name,tk))

    def pay_func(person,payway,money,tk):
    if payway == 'alipay':
    per = AliPay(person)
    elif payway == 'wechatpay':
    per = WeChatPay(person)
    elif payway == 'applepay':
    per = ApplePay(person)
    per.pay(money)
    per.back(tk)

    pay_func('张飞','alipay',200,100)
    pay_func('关羽','wechatpay',300,100)
    pay_func('刘备','applepay',4200,100)主要是解决同事协作之间的代码规范问题
    规定:(上例中)Payment 就是一个规范类,这个类存在的意义不在于实现实际的功能,而是为了约束所有的子类必须实现pay的方法
    Payment : 抽象类
    pay = Payment() # 抽象类: 不能实例化
    抽象类主要就是作为基类/父类,来约束子类中必须实现的某些方法
    抽象类的特点:
         from abc import ABCMeta,abstractmethod
            必须在类定义的时候指定metaclass = ABCMeta
    必须在要约束的方法上方加上@abstractmethod方法
    粗略使用:
    from abc import ABCMeta,abstractmethod #(抽象方法)
    class Payment(metaclass=ABCMeta): # metaclass 元类 metaclass = ABCMeta表示Payment类是一个规范类
    @abstractmethod # @abstractmethod表示下面一行中的pay方法是一个必须在子类中实现的方法
    def pay(self):pass

    @abstractmethod
    def back(self):pass # 退款功能

    class ApplePay(Payment):
    def pay(self):
    pass
    def back(self):
    pass

    接口类:
    java 不支持多继承
    python 支持多继承 :通过抽象类的多继承来实现复杂的规范
    不同动物的相同行为是不能混为一谈
    不同动物的相同行为的方法名字是必须一样

    python
    抽象类 : 抽象类中的方法可以写一些具体的py代码(规范)
    单继承
    多继承

    java
    不支持多继承,新的概念 接口 Interface
    和抽象类几乎一模一样的功能 :
    只定义一个接口名字(基类名),内部定义子类必须实现的方法
    接口支持多继承
    接口内部的所有方法都不能写具体的代码,只能用pass代替

    抽象类 :
    单继承的形容,并且在单继承中可以在方法中写python代码
    接口类 : 更接近java中的接口的概念
    python中由于有了抽象类的多继承,不需要接口的概念了
    一个基类写出来被子类多继承了 : 接口类
    并且在方法中只写pass(你可以选择性的满足)

    
    

    案例说明
    动物园
    天鹅 : 飞 走 游泳
    老虎 : 走 游泳
    鹦鹉 : 飞 走 说话
    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 :两种类
    python3 :只有一种类
    新式类 : 默认继承object类 # object 是所有类的父类
    为什么可以不写__init__?
    所有object中的类都是你自己不写也可以调用的
    区别
    钻石继承问题/多继承的优先级问题
    在python3中 所有的类都是新式类,所有的新式类的继承顺序都遵循C3算法,也叫广度优先算法
    可以使用类名.__mro__()这个方法来查看这个继承顺序


    案例说明:
    class A:
    pass
    def func(self):print('A')

    class B(A):
    pass
    def func(self):print('B')

    class C(A):
    pass
    def func(self):print('C')

    class D(B):
    pass
    def func(self):print('D')

    class E(C):
    pass
    def func(self):print('E')

    class F(D,E):
    pass
    # def func(self):print('F')
    f= F()
    f.func()



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

    L(B) = [B] + [AO]
    B = [AO]
    BA = [O]
    L(B) = [BAO]

    L(C) = [C] + [AO]
    C = [AO]
    CA = [O]
    L[C] = [CAO]

    L[D] = [D] + [BAO] + [CAO]
    D = [BAO] + [CAO]
    DB = [AO] + [CAO]
    DBC = [AO] + [AO]
    DBCA = [O] + [O]
    L[D] = DBCAO


     
     
     


  • 相关阅读:
    SAM4E单片机之旅——2、LED闪烁之轮询定时器
    SAM4E单片机之旅——1、LED闪烁之空循环
    C#使用WinAPI 修改电源设置,临时禁止笔记本合上盖子时睡眠
    阻止系统自动睡眠的小软件,附C#制作过程
    Python3做采集
    判断浏览器类型
    任意几个数求和
    常见Z纯CSS小样式合集(三角形)
    数据脱敏项目中遇见的问题
    点击左侧跳到右侧
  • 原文地址:https://www.cnblogs.com/Godisgirl/p/10004580.html
Copyright © 2011-2022 走看看