zoukankan      html  css  js  c++  java
  • OOP三大特征之继承

    • 继承

    • 什么是继承:两个对象之间的关系,一个称为子类,一个称为父类,其中子类继承着父类的属性以及方法技能,可以直接使用。(值得注意的是:在python3中所有创建的类都直接或间接,隐性或显性的继承object类,如果没有显示继承某个类,则默认继承的是object类,又称为新式类)

    • 为什么要使用继承:减少代码的复用

    • 用代码如何表示

    • class Base:
          character  = '我是父类'
          def want_basketball(self):
              print('教练我想打篮球')
      
      class SubClass(Base):               # 通过在子类的括号之中加父类的名称
          pass
      
      obj = SubClass()
      obj.want_basketball()               # 直接调用父类的方法 如果属性和方法完全一样的话
      print(obj.character)

      比如好人,坏人,黄种人,白种人,黑人都是人这个大类的继承,而他们都是抽象而生成人这个类的。

    • 那么当子类和父类有属性和方法有冲突时,是不是就不可以用继承方法呢?显然不是,一般来说我们可以将子类和父类的共同特征都提取出来,专业名词可以称之为抽象,将抽象完的一个新的类作为共同大类,供上述子类和父类使用。

    • 就以足球和篮球运动员为例,对于他们来说都是人类,都有名字性别和身高等特征,但是他们会的技能不一样
    • class Person:
          def __init__(self,name,height,gender):          # 定义抽象得来的公共类
              self.name = name
              self.height = height
              self.gender = gender
      
      class FootBallPlayer(Person):                       # 通过子类名括号里面加抽象父类名起到继承的作用
          def Skill(self):
              print('%s会踢足球'%(self.name))
      
      class BasketBallPlayer(Person):
          def Skill1(self):
              print('%s会打篮球'%(self.name))
      
      
      
      Kobe = BasketBallPlayer('kobe Bryant','189','male')     # 名字身高等信息就不需要通过父类调用,直接子类调用
      Kobe.Skill1()
      Messi = FootBallPlayer('Lion Messi','176','male')
      Messi.Skill()
    • 存在继承关系后的属性查找

    • 一个类必然继承另一个类,被继承的类也有可能继承了其他类,相当于C继承B,B又继承A

    • 此时查找属性的顺序是:

      对象本身的名称空间 - > 类的名称空间 -> 父类的名称空间 -> 父类的父类名称空间 ->...object类

      会沿着继承关系一直往后查找,直到找到为止,由于object是所有类的根类,所以如果找不着最后都会查找object类!

    • class Foo:
          def f1(self):
              print('Foo.f1')
      
          def f2(self):
              print('Foo.f2')
              self.f1()
      
      class Bar(Foo):
          def f1(self):
              print('Bar.f1')
      
      
      b=Bar()
      b.f1()
      #输出 Bar.f1
      b.f2()
      #输出 Foo.f2
    • 派生和覆盖

    • 派生的定义:当父类提供的属性无法完全满足子类的需求时,子类可以增加自己的属性或方法,或者覆盖父类已经存在的属性,此时子类称之为父类的派生类;

    • 覆盖的定义:如果子类中出现于与父类相同的属性以及方法时,程序要调用,会优先使用子类中的属性。
    • 很多情况下 子类中的代码与父类中仅有小部分不同,却不得不在子类定义新的方法,这时候可以在子类中调用父类已有的方法,来完成大部分工作,子类仅需编写一小部分与父类不同的代码即可

    • 有两种方式可以重用父类的属性和方法

    • 使用类名直接调用 ,该方式与继承没有关系,即时没有继承关系,也可以调用
    • 使用super()
    • class Person:
          def __init__(self,name,height,gender):          # 定义抽象得来的公共类
              self.name = name
              self.height = height
              self.gender = gender
      
      class FootBallPlayer(Person):                       # 通过子类名括号里面加抽象父类名起到继承的作用
          def __init__(self,name,height,gender,field):    # 如果不写这两行 将不能调用name height gender属性
              super().__init__(name,height,gender)        # 重用父类中的代码,防止覆盖了父类中的init方法
              self.field = field
          def Skill(self):
              print('%s会踢足球'%(self.name))
              print(self.height,self.gender,self.field)
      Messi = FootBallPlayer('Lion Messi','176','male','grass')
      Messi.Skill()
    • 组合

    • 当两个类之间没有太大的联系的时候,或者说它们不属于同类时,当一个对象要使用另一个对象的属性,这就叫做组合的概念。

    • class Equip:  # 武器装备类
          def fire(self):
              print('release Fire skill')
      
      
      class Riven:  # 英雄Riven的类,一个英雄需要有装备,因而需要组合Equip类
          camp = 'Noxus'
      
          def __init__(self, nickname):
              self.nickname = nickname
              self.equip = Equip()  # 用Equip类产生一个装备,赋值给实例的equip属性
      
      
      r1 = Riven('锐雯雯')
      r1.equip.fire()  # 可以使用组合的类产生的对象所持有的方法
    • 继承实现的原理

    • 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中才分新式类与经典类
      
      继承顺序
    • 继承实质

    • python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如
    • >>> F.mro() #等同于F.__mro__
      [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>
    • 所有父类的MRO列表并遵循如下三条准则:

      1.子类会先于父类被检查

      2.多个父类会根据它们在列表中的顺序被检查

      3.如果对下一个类存在两个合法的选择,选择第一个父类

  • 相关阅读:
    mysql5.5 uuid做主键与int做主键的性能实测
    dom4j解析xml字符串实例
    spring自动注入是单例还是多例?单例如何注入多例?
    Spring中Bean的五个作用域
    【总结】瞬时高并发(秒杀/活动)Redis方案
    浅谈分布式事务
    基于Redis实现分布式锁
    MySQL事务隔离级别详解
    Redis学习手册(Sorted-Sets数据类型)
    Redis的快照持久化-RDB与AOF
  • 原文地址:https://www.cnblogs.com/ITchemist/p/11247632.html
Copyright © 2011-2022 走看看