zoukankan      html  css  js  c++  java
  • 面向对象(二)--继承与派生、组合

    一、什么是继承

    继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。

    二、继承的特点

    1.继承描述的是事物的遗传关系,子类可以重用父类的属性,需要注意的是:继承是类与类之间的关系!!好处就是可以减少类之间的代码冗余问题

    2.在Python中支持一个子类继承多个父类

    3.Python类分为两种:新式类、经典类

      (1)新式类: 但凡继承了object的类Foo,以及该类的子类...都是新式类

        在python3中一个类即便是没有显式地继承任何类,默认就会继承object,即python3中所有的类都是新式类

      (2)经典类:没有继承object的类,以及该类的子类...都是经典类

        在python2中才区分新式类与经典类,在python2中一个类如果没有显式地继承任何类,也不会继承object

    三、单继承和多继承

    class Parent1():
        a = 3
    
    class Parent2():
       a = 3
    
    class Sub1(Parent1):         # 单继承,父类是Parent1,子类是Sub1
        a = 2
        pass
    
    
    class Sub2(Parent1,Parent2):       # 多继承,父类是Parent1,Parent2,子类是Sub1
        a = 2
        pass

    四、查看继承

    利用__bases__方法可以查看子类的父类,只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
    
    class Parent1():
        pass
    
    class Sub1(Parent1):
        pass
    
    print(Sub1.__bases__)

    五、继承的实现原理

    C3算法与方法解析顺序(MRO)列表

    属性查找的原则:

    1. 子类先于父类被查找
    2. 有多个父类时,会根据它们在列表中的顺序被查找
    3. 如果对下一个类存在两个合法的选择,则选择第一个父类

    mro列表只适用于新式类,经典类不存在mro列表

    只有在python2中才有经典类与新式类的区分,python3中全部是新式类

    六、子类重用父类中的方法(派生)

    1、派生:在子类中定义自己的属性,如果与父类的属性重名,那以自己的为准

    2、在子类派生出的新方法中重用父类功能的方式一:指名道姓地访问父类中的函数

      Foo.__init__(self,name,age)     不能自动传值,有几个参数就传几个

    (1)该方式与继承无关

    (2)没有自动传值的效果

    class People():
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    
    class Student(People):
        def __init__(self, name, age, sex, score=0):
            # 方式一 调用父类中的__init__函数
            People.__init__(self, name, age, sex)
            self.score = score
    
        def choose(self):
            print('%s choosing course' % self)
    
    
    class Teacher(People):
        def score(self, stu, score):
            stu.score = score
    
    
    stu = Student('张三', 12, 'male')
    print(stu.__dict__)      # __dict__可以查看对象的名称空间中的名字
    方式一

    3、在子类派生出的新方法中重用父类功能的方式二:super(),只能在子类中用

      super().__init__(name,age)    自动传值

    (1)在python2中:super(自己的类名,自己的对象)

      在python3:super()    

      调用super()会得到一个特殊的对象,该特殊的对象是专门用来引用父类中的属性的,!!!完全参照mro列表!!!

    (2)super()注意点:

      a. 该方式与继承严格依赖于继承的mro列表,类名.mro()      ===>  不管有没有继承关系,super()都是根据mro往后查找
      b. 访问是绑定方法,有自动传值的效果

    class People():
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    
    class Student(People):
        def __init__(self, name, age, sex, score=0):
            super().__init__(name,age,sex)
            self.score = score
    
        def choose(self):
            print('%s choosing course' % self)
    
    
    class Teacher(People):
        def score(self, stu, score):
            stu.score = score
    
    
    stu = Student('张三', 12, 'male')
    print(stu.__dict__)  # 查看对象的名称空间
    方式二

    七、继承背景下的属性查找

    1、单继承背景下的属性查找

    单继承背景下属性查找顺序:对象的名称空间------>对象的类的名称空间------->父类的名称空间

    class Foo:
         x=333
         pass
    
    class Bar(Foo):
    #     x=222
         pass
    
    obj=Bar()
    # obj.x=111
    print(obj.x)   # 333
    单继承背景下的属性查找

    2、多继承背景下的属性查找

    多继承背景下属性查找的顺序:对象的名称空间------>对象的类的名称空间-------->按照从左往右的顺序一个一个的分支找下去

    # 查找顺序是 obj-->A-->B-->E-->C-->F-->I-->D-->H
    
    #第四层
    class I:
        # x='I'
        pass
    
    #第三层
    
    class E:
        # x='E'
        pass
    
    class F(I):
        # x='F'
        pass
    
    class H:
        x='H'
    
    # 第二层
    class B(E):
        # x='B'
        pass
    
    class C(F):
        # x='C'
        pass
    
    class D(H):
        # x='D'
        pass
    
    #第一层
    class A(B,C,D):
        # x='A'
        pass
    
    obj=A()
    # obj.x=111
    print(obj.x)
    多继承背景下属性查找

    八、继承顺序

    1、在Java和C#中子类只能继承一个父类,而Python中子类可以同时继承多个父类,如A(B,C,D)

    2、如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性

    如果继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先

    九、组合

    1、什么是组合

    组合指的是某一个对象拥有一个属性,该属性的值是另外一个类的对象

    class Foo():
        pass
    
    class Bar():
        pass
    
    obj=Bar()
    obj.attrib=Foo()

    2、组合的作用

    通过为某一个对象添加属性(属性值是另外一个类的对象)的方式,可以间接地将两个类关联/整合/组合到一起,从而减少类与类之间代码冗余

    3、组合的使用

    class OldboyPeople:
        school = 'oldboy'
    
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    
    class OldboyStudent(OldboyPeople):
    
        def __init__(self, name, age, sex, score=0):
            super().__init__(name, age, sex)
            self.score = score
            self.courses = []
    
        def choose_course(self):
            print('%s choosing course' % self.name)
    
        def tell_all_course(self):
            print(('学生[%s]的课程如下' % self.name).center(60, '='))
            for course in self.courses:
                course.tell_course()
            print('=' * 80)
    
    
    class OldboyTeacher(OldboyPeople):
    
        def __init__(self, name, age, sex, level):
            super().__init__(name, age, sex)
            self.level = level
            self.courses = []
    
        def score(self, stu, num):
            stu.score = num
    
        def tell_all_course(self):
            print(('老师[%s]教授的课程如下' % self.name).center(70, '-'))
            for course in self.courses:
                course.tell_course()
            print('-' * 80)
    
    
    class Course:
        def __init__(self, c_name, c_price, c_period):
            self.c_name = c_name
            self.c_price = c_price
            self.c_period = c_period
    
        def tell_course(self):
            print('<课程名:%s 价格:%s 时间:%s>' % (self.c_name, self.c_price, self.c_period))
    
    
    python = Course('python全栈开发', 10000, 5)
    linux = Course('linux架构', 12000, 5)
    
    stu = OldboyStudent('zs', 18, 'male')
    stu.courses.append(python)
    stu.courses.append(linux)
    stu.tell_all_course()
    
    teach = OldboyTeacher('egon', 18, 'male', 10)
    teach.courses.append(python)
    teach.tell_all_course()
    组合的使用

    软件重用的重要方式除了继承之外的另一种方式就是组合。

    组合和继承都是有效的利用已有类的资源的重要方式,但使用场景和概念却都不同:

    1、继承的方式:

      通过继承建立了派生类与基类之间的关系,是一种“是”的关系。

    2、组合的方式:

      用组合的方式建立了类与组合的类之间的关系,是一种“有”的关系。

    #当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合会更好。

  • 相关阅读:
    Java 9将采用新的版本字符串格式
    Hadoop单机伪分布式
    Hadoop JAVA 开发说明
    Java 批量插入数据(Oracle)
    Myeclipse 的hadoop环境搭建
    [LeetCode] 136. Single Number 单独数
    [LeetCode] 89. Gray Code 格雷码
    [LeetCode] 209. Minimum Size Subarray Sum 最短子数组之和
    [LeetCode] 211. Add and Search Word
    [LeetCode] 152. Maximum Product Subarray 求最大子数组乘积
  • 原文地址:https://www.cnblogs.com/zhangbingsheng/p/10115017.html
Copyright © 2011-2022 走看看