面向对象之继承

一, 什么是面向对象的继承?

  1. 继承是面向对象软件技术当中的一个概念.如果一个类别A'继承自'另一个类别B,就把这个A称作'B的子类别',而把B称为'A的父类别',也可以说'B是A的超类'.继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码.在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能.

    # 看一个继承的例子
    class Person:
        def __init__(self, name, sex, age):
            self.name = name
            self.sex = sex
            self.age = age
    class Cat:
        def __init__(self, name, sex, age):
            self.name = name
            self.sex = sex
            self.age = age
    class Dog:
        def __init__(self, name, sex, age):
            self.name = name
            self.sex = sex
            self.age = age
    # 是不是很麻烦,我们来看一下继承
    class Animal:
        def __init__(self, name, sex, age):
            self.name = name
            self.sex = sex
            self.age = age
    class Person(Animal):
        pass
    class Cat(Animal):
        pass
    class Dog(Animal):
        pass
    # Aminal叫做父类,基类,超类
    # Person Cat Dog: 子类,派生类
    
  2. 继承的优点显而易见:

    1. 增加了类的耦合性(耦合性不宜多,宜精)
    2. 减少了重复代码
    3. 使得代码更加规范化,合理化

二, 继承的分类

  1. 补充一下python中类的种类

    1. python 2中存在两种类:
      • 经典类: python 2.2之前一直使用的是经典类,经典类的基类的根什么都不写
      • 新式类: python 2.2之后出现了新式类,新式类的特点是基类的根是object类
    2. 在python 3版本中只有一种类:
      • python 3中使用的都是新式类,如果基类谁都不继承,那这个类会默认继承object
  2. 单继承

    1. 类名,对象执行父类方法

      class Animal(object):
          type_name = '动物类'
          def __init__(self, name, sex, age):
              self.name = name
              self.sex = sex
              self.age = age
          def eat(self):
              print(self)
              print('吃东西')
      
      class Person(Animal):
          pass
      class Cat(Animal):
          pass
      class Dog(Animal):
          pass
      
      # 类名:
      print(Person.type_name) # 可以调用父类的属性,方法
      Person.eat(1)
      ------------------------------------------------
      # 对象:
      # 实例化对象
      p1 = Person('元始天尊', '男', 18)
      print(p1.__dict__)
      # 对象执行类的父类的属性,方法
      print(p1.type_name)
      p1.type_name = '666'
      print(p1.type_name)
      p1.eat()
      
    2. 执行顺序

      # 执行顺序
      class Animal(object):
          type_name = '动物类'
          def __init__(self, name, sex, age):
              self.name = name
              self.sex = sex
              self.age = age
          def eat(self):
              print(self)
              print('吃东西')
      
      class Person(Animal):
          def eat(self):
              print(f'{self.name}吃饭')
      class Cat(Animal):
          pass
      class Dog(Animal):
          pass
      p1 = Person('太上老君', '男', 18)
      # 实例化对象时必须执行__init__方法,类中没有,父类没有,从object类中找
      p1.eat()
      # 先要执行自己类中的eat方法,自己类没有才能执行父类中的方法
      
    3. 同时执行类以及父类的方法

      # 方法一:
      # 如果想执行父类的func方法,这个方法并且子类中也有,那么就在子类的方法中写上: 父类.func(对象,其他参数)
      
      class Animal(object):
          type_name = '动物类'
          def __init__(self, name, sex, age):
              self.name = name
              self.sex = sex
              self.age = age
          def eat(self):
              print(self)
              print('吃东西')
      
      class Person(Animal):
          def __init__(self, name, sex, age, mind):
              Animal.__init__(self, name, sex, age) # 方法一
              self.mind = mind
          def eat(self):
              print(f'{self.name}吃饭')
      class Cat(Animal):
          pass
      class Dog(Animal):
          pass
      
      p1 = Person('孙悟空', '男', 18, '有思想')
      print(p1.__dict__)
      
      -------------------------------------------------
      # 方法二: 利用super,super().func(参数)
      class Animal(object):
          type_name = '动物类'
          def __init__(self, name, sex, age):
              self.name = name
              self.sex = sex
              self.age = age
          def eat(self):
              print(self)
              print('吃东西')
      
      class Person(Animal):
          def __init__(self, name, sex, age, mind):
              # super(Person, self).__init__(name, sex, age) # 方法二
              super().__init__(name, sex, age) # 方法二
              self.mind = mind
          def eat(self):
              print(f'{self.name}吃饭')
      class Cat(Animal):
          pass
      class Dog(Animal):
          pass
      p1 = Person('嫦娥', '女', 18, '有思想')
      print(p1.__dict__)
      
  3. 多继承

    # 例
    class God:
        def __init__(self, name):
            self.name = name
        def fly(self):
            print('会飞')
        def climb(self):
            print('神仙也会爬树')
    class Monkey:
        def __init__(self, sex):
            self.sex = sex
        def climb(self):
            print('会爬树')
    class MonkeySun(God, Monkey): # 多继承
        pass
    sun = MonkeySun('孙悟空')
    sun.climb()
    sun.fly()
    
    1. 经典类的多继承

      # 虽然在python3中已经不存在经典类了,但是经典类的MRO最好还是学一下,这是树形结构遍历的一个最直接的案例,在python的继承体系中,我们可以把类与类继承关系画成一个树形结构的图
      class A:
          pass
      class B(A):
          pass
      class C(A):
          pass
      class D(B, C):
          pass
      class E:
          pass
      class F(D, E):
          pass
      class G(F, D):
          pass
      class H:
          pass
      class Foo(H, G):
          pass
      print(Foo.mro())
      # 查找原则: 在经典类中采用的时深度优先遍历方案,就是一条路走到头,然后再回来,继续找下一个
      


    2. 新式类的多继承: MRO序列

      # MRO是一个有序列表L,在类被创建时就计算出来,计算公式为:
      mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )
      # (其中Child继承自Base1, Base2)
      --------------------------------------------------------------
      # 如果继承至一个基类: class B(A)
      # 这时B的mro序列为
      mro(B) = mro( B (A) )
             = [B] + merge( mro(A) + [A] )
             = [B] + merge( [A] + [A] )
             = [B,A]
      --------------------------------------------------------------
      # 如果继承至多个基类: class B(A1,A2,A3...)
      # 这时B的mro序列
      mro(B) = mro( B(A1,A2,A3...))
             = [B] + merge( mro(A1),mro(A2),mro(A3)...,[A1,A2,A3] )
             = ...
           
      # 计算结果为列表,列表中至少有一个元素,即类自己,如上述示例[A1,A2,A3],merge操作是C3算法的核心
      --------------------------------------------------------------
      # 表头和表尾
      # 表头: 列表的第一个元素
      # 表位: 列表中表头以外的元素集合(可以为空)
      # 示例: 列表[A,B,C] 表头是A,表尾是B和C
      
      # 列表之间的+操作: [A] + [B] = [A,B]
      --------------------------------------------------------------
      # 示例: 计算merge( [E,O], [C,E,F,O], [C] )
      # 1. merge不为空,取出第一个列表[E,O]的表头E,进行判断,各个列表的表尾分别是[O],[E,F,O]
      #    因为E在这些表尾的集合中,因而跳过当前列表
      # 2. 取出第二个列表[C,E,F,O]的表头C,进行判断,各个列表的表尾分别是[O],[E,F,O]
      #    因为C不在这些表尾的集合中,因而将C拿出到merge外,并将所有表头为C的删除
      #    merge( [E,O], [C,E,F,O], [C] ) = [C] + merge( [E,O], [E,F,O])
      # 3. 进行下一次新的merge操作...
      
      

      # mro(A) = mro( A(B,C) )
      # 原式 = [A] + merge( mro(B), mro(C), [B,C] )
      #
      # mro(B) = mro( B(D,E) )
      #        = [B] + merge( mro(D), mro(E), [D,E] ) # 多继承
      #        = [B] + merge( [D,O], [E,O], [D,E] )   # 单继承mro(D(O)) = [D,O]
      #        = [B,D] + merge( [O], [E,O], [E] )     # 拿出并删除D
      #        = [B,D,E] + merge( [O], [O] )          # 拿出并删除E
      #        = [B,D,E,O]
      #
      # mro(C) = mro( C(E,F) )
      #        = [C] + merge( mro(E), mro(F), [E,F] )
      #        = [C] + merge( [E,O], [F,O], [E,F] )
      #        = [C,E] + merge( [O], [F,O], [F] )
      #        = [C,E,F] + merge( [O], [O] )
      #        = [C,E,F,O]
      # 原式 = [A] + merge( [B,D,E,O], [C,E,F,O], [B,C] )
      #      = [A,B] + merge( [D,E,O], [C,E,F,O], [C] )
      #      = [A,B,D] + merge( [E,O], [C,E,F,O], [C] )
      #      = [A,B,D,C] + merge( [E,O], [E,F,O] )
      #      = [A,B,D,C,E] + merge( [O], [F,O] )
      #      = [A,B,D,C,E,F] + merge( [O], [O] )
      #      = [A,B,D,C,E,F,O]
      
posted @ 2019-07-09 16:10  怀心抱素  阅读(828)  评论(0编辑  收藏  举报