zoukankan      html  css  js  c++  java
  • 面向对象三大特征之继承

    面向对象三大特性之继承

      1.什么是继承?

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

        子类会“遗传”父类的属性,从而解决代码重用问题。

      2.继承的使用

        在子类中,类名后面加上括号,写上父类的名称即可(在Python中一个子类可以有多个父类,多个父类在括号中庸逗号分隔开)

    class Parent:   #父类
        year = 2018
        def coding(self):
            print("正在编程........")
    
    class Sub(Parent):    #子类
        pass
    print(Parent.year)
    print(Sub.year)
    # Sub.coding()
    s = Sub()
    print(s.year) # 子类可以使用父类中的属性
    s.coding() # 子类也可以父类中的函数
    
    #打印结果
    2018
    2018
    2018
    正在编程........

      3.经典类与新式类

        所有直接继承或者间接继承object的类都是新式类,object称之为根类,意思是所有类都源自于object类。

        例如:在创建对象时,需要申请内存空间,创建新的名称空间,将对象属性放入名称空间,这些复杂的基础操作都由object来完成。简单来说,object提供了一些常用的基础操作。

      python2与python3 的区别: 

        1.只有在python2中才分新式类和经典类,python3中统一都是新式类

        2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类

        3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类

        4.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类

    class S:
        pass
    class Student(S):
        pass
    
    # __bases__用于查看父类
    print(Student.__bases__)
    
    # 显示属性的查找顺序列表,属性查找属性就是按照该列表来查找的
    print(Student.mro())
    经典类与新式类

      4.抽象(先抽象再继承)

        继承描述的是子类和父类之间的关系,是一种什么是什么的关系。要找出着这种关系,必须先继承再抽象。抽象即抽取类似或者比较像的部分。

        抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度),

                

        继承是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。

        抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类。

                   

    class Person:
        def __init__(self ,name ,age ,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def eat(self):
            print("正在吃饭....")
    
        def study(self):
            print("正在学习....")
    
    class Teacher(Person):
    
        def teaching(self):
            print("老师正在上课......")
    
    t1 = Teacher("blex" ,30 ,"woman")
    t1.eat()
    t1.study()
    
    class Student(Person):
        pass
    
    stu1 = Student("张三" ,20 ,"man")
    stu1.eat()
    stu1.study()
    
    # stu1.teaching()
    抽象

    上述例子中,学生继承老师,可以减少重复代码,但是继承到一些学生不应该有的内容teaching。所以,应该先抽象,抽取出公共的父类。通过继承,避免了重复代码的编写,通过抽象,避免继承到一些不应该有的内容,公共父类的作用是存储多个子类相同的属性。

       5.派生

        派生指的是子类继承某个父类,并且拥有自己独特的属性或者技能,该子类称为派生类。只要子类中出现任何新内容,它就是一个派生类。需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用的属性时,就以自己为准了。

        在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能,应该是用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值。

        子类出现了与父类重复的名字称之为覆盖。子类出现了与父类不同的名字称之为派生。

    class Person:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def sayHI(self):
            print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))
    
    # Test不能称为派生类 , 因为没与任何独特的内容与父类完全一致
    class Test(Person):
        pass
    
    class Student(Person):
        def __init__(self,name,age,sex,number):
            self.name = name
            self.age = age
            self.sex = sex
            self.number = number
    
        # 上课
        def up_class(self):
            print("%s 正在上课.....")
    派生

      派生类一定是某个子类,但是子类不一定是派生类。

      6.子类访问父类的方法

        在子类派生出的新功能中如何重用父类的功能:

          方式一:指名道姓地访问某一个类中的函数,与继承无关。

          方式二:super()表示创建一个特殊的对象,用于调用父类的方法。(super一定用在存在继承关系的子类中)在python3中super函数可以不传参数,调用该函数会得到一个特殊的对象,该对象是专门用来访问父类中属性。在python2中,需要传入当前类,当前对象。

        强调:super会严格参照类的mro列表一次查找属性

    class Person:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
            print(self)
    
        def sayHI(self):
            print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))
    
    class Student(Person):
        def __init__(self,name,age,sex,number):
            # self.name = name
            # self.age = age
            # self.sex = sex
            # 子类中重用父类种方法的方式2
            # super() # 表示创建一个特殊的对象 用于调用父类的方法
            # super().__init__(name,age,sex)
            # 了解:在python2中 super的使用方式有所不同 需要传入当前类,当前对象
            super(Student,self).__init__(name,age,sex)
            self.number = number
    
        # 上课
        def up_class(self):
            print("%s 正在上课.....")
    
    stu1 = Student("阿三",20,"woman","9527")
    print(stu1)
    print(stu1.name,stu1.age,stu1.sex)
    子类访问父类的方法

      7.属性查找顺序

        在单继承背景下,无论是新式类还是经典类属性查找顺序都是一样的,先obj—>类—>父类—>...

    class Foo:
        def f1(self):
            print('Foo.f1')
    
        def f2(self):
            print('Foo.f2')
            self.f1() #obj.f1()
    
    class Bar(Foo):
        def f1(self):
            print('Bar.f1')
    
    obj=Bar()
    obj.f2()
    单继承

        在多继承背景下,如果一个子类继承了多个分支,但是多个分支没有汇聚到一个非object类,无论是新式类还是经典类属性查找顺序都一样:会按照从左到右的顺序一个分支一个分支的查找下去

    class E:
        # xxx='E'
        pass
    
    class F:
        # xxx='F'
        pass
    
    class B(E):
        # xxx='B'
        pass
    
    class C(F):
        # xxx='C'
        pass
    
    class D:
        # xxx='D'
        pass
    
    class A(B,C,D):
        # xxx='A'
        pass
    
    obj=A()
    # obj.xxx=111
    # print(obj.xxx)
    View Code

        在多继承背景下,如果一个子类继承了多个分支,但是多个分支最终汇合到一个非object类(菱形继承问题)。

        新式类:广度优先查找:obj->A->B->E->C->F->D->G->object

        经典类:深度优先查找:obj->A->B->E->G->C->F->D

    class G:
        xxx='G'
    
    class E(G):
        xxx='E'
        pass
    
    class F(G):
        xxx='F'
        pass
    
    class B(E):
        xxx='B'
        pass
    
    class C(F):
        xxx='C'
        pass
    
    class D(G):
        xxx='D'
        pass
    
    class A(B,C,D):
        xxx='A'
        pass
    print(A.mro())
    多继承

        

  • 相关阅读:
    627. Swap Salary
    176. Second Highest Salary
    596. Classes More Than 5 Students
    183. Customers Who Never Order
    181. Employees Earning More Than Their Managers
    182. Duplicate Emails
    175. Combine Two Tables
    620. Not Boring Movies
    595. Big Countries
    HDU 6034 Balala Power! (贪心+坑题)
  • 原文地址:https://www.cnblogs.com/liuxiaolu/p/10120210.html
Copyright © 2011-2022 走看看