Python-继承(单继承&多继承)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Katherine_hsr/article/details/82377643

面向对象有三大特性:封装、继承和多态
封装:根据职责将属性和方法封装到一个类中
继承:可以实现代码重用,相同的代码不需要重复编写
多态:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度

为什么需要继承

首先我们看以下的一个例子
这里写图片描述
我们有以下几个类:Animal:其中封装了drink, eat, run 和sleep四个方法, Dog:其中也封装了eat, drink, run, sleep, 除此之外还有一个bark方法。如果不使用继承,我们需要定义两个类,其中需要封装所有的类中包含的方法,这样就需要我们重复写eat, drink, run, sleep着四个方法。再来看XiaoTianQuan这个类,其内部有Dog类中的五个方法,仅仅多了一个fly方法,需要重复写狗类中的五个方法。同时,如果我们需要修改Animal类中的eat方法,我们需要同时修改Dog类中和XiaoTianQuan类中的eat方法。所以我们需要使用继承特性,使相同的代码不需要重复编写。

继承的语法

在上面的图中,我们可以把Dog看成子类,Animal看成父类,子类具有父类中所有的属性和方法,子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发,子类中应该根据职责,封装子类特有的属性和方法。
继承的使用方法如下

class 子类(父类):
    pass

以上图为例,我们利用继承创建一个Animal父类和一个Dog子类

class Animal:

    def drink(self):
        print("drink")

    def eat(self):
        print("eat")

    def run(self):
        print("run")

    def sleep(self):
        print("sleep")

class Dog(Animal):

    def bark(self):
        print("bark")

dog = Dog()
dog.eat()
dog.run()
dog.bark()
dog.drink()
dog.sleep()

在Dog类中,我们虽然没有写eat, run, drink, sleep方法,但是可以继承Animal类中的这些方法。
对于Dog类和Aniamal类,我们可以说Dog类是Animal类的子类,Animal类是Dog类的父类,Dog类从Animal类中继承。或者说Dog类是Animal类的派生类,Animal类是Dog类的基类,Dog类从Animal类中派生。

继承的传递性

C类从B类中继承,B类从A类中继承,那么C类就拥有B类和A类中所有的属性和方法。也就是说子类中拥有父类以及父类的父类中的所有封装的属性和方法。

方法的重写

子类继承父类中的所有属性和方法,可以直接享有父类中已经封装好的熟悉和方法,不需要再次开发。
但是在实际情况中,如果父类的方法实现不能满足子类的需求时,就需要对父类的方法进行重写(override)。
这里写图片描述
例如在上面的类图中,Dog类继承自Animal类,然后XiaoTianQuan类继承在Dog类,但是XiaoTianQuan类中的bark()方法和Dog类中的bark()方法不一样,这时我们就需要在定义XiaoTianQuan类时对bark()方法进行重写。
重新父类的方法有两种形式:
1. 覆盖父类的方法 :
如果在开发过程中,父类的方法实现和子类的方法实现完全不同就可以用覆盖的方式,在子类中重新编写父类的方法实现。具体实现的方式就相当于在子类中重新定义了一个和父类同名的方法并且实现,重写之后在运行时只会调用子类中的重新的方法,而不会再调用父类封装的方法。
下面是用覆盖父类的方法的代码示例:

class Animal:

    def eat(self):

        print("eat")

    def drink(self):

        print("drink")

    def sleep(self):

        print("sleep")

    def run(self):

        print("run")


class Dog(Animal):

    def bark(self):

        print("bark")


class XiaoTianQuan(Dog):

    def fly(self):

        print("fly")

    def bark(self):

        print("xiaotianquan fly")


xtq = XiaoTianQuan()

xtq.bark()

运行输出“xiaotianquan fly”而不是“fly”,说明子类调用了自己的方法而不是父类的方法
2. 对父类的方法进行扩展:
如果在开发过程中,子类的方法实现中包含父类的方法实现,也就是说原本父类封装的方法实现是子类方法的一部分,这时候就可以使用扩展的方法。对父类方法进行扩展有以下3个步骤:
1. 在子类中重写父类的方法
2. 在需要的位置使用super().父类方法来调用父类方法的执行
3. 代码其他的位置针对子类的需求,编写子类特有的代码实现
下面是将上面对覆盖父类方法更改为在子类中重写父类方法代码:

class Animal:

    def eat(self):

        print("eat")

    def drink(self):

        print("drink")

    def sleep(self):

        print("sleep")

    def run(self):

        print("run")


class Dog(Animal):

    def bark(self):

        print("bark")


class XiaoTianQuan(Dog):

    def fly(self):

        print("fly")

    def bark(self):

        # 在子类中重写父类的方法
        print("xiaotianquan fly")

        # 在需要的位置使用super().父类方法来调用父类方法的执行
        super().bark()

        # 代码其他的位置针对子类的需求,编写子类特有的代码实现
        print("子类特有的代码实现")

运行上述代码可以输出以下结果:
xiaotianquan fly
bark
子类特有的代码实现
关于 super
1. 在 Python 中 super 是一个 特殊的类
2. super() 就是使用 super 类创建出来的对象
3. 最常使用的场景就是在重写父类方法时,调用在父类中封装的方法实现

父类的私有属性和私有方法

子类对象不能在自己的方法内部直接访问父类的私有属性或私有方法,子类对象可以通过父类的公有方法间接访问到私有属性或私有方法。

多继承

子类可以拥有多个父类,并且具有所有父类的属性和方法
多继承的语法如下:

class 子类名(父类名1, 父类名2, ...):
    pass

下面是一个多继承的示例:

class A:

    def demo(self):
        print("demo 方法")


class B:

    def test(self):
        print("test 方法")


class C(A, B):

    pass


c = C()
c.demo()
c.test()

C类可以同时继承A类和B类中的方法。

多继承的使用注意事项

如果不同的父类具有同名的方法或属性,那么子类在继承时应该尽量避免选择多继承。在下面的示例中,C类同时继承A类和B类,但是A类和B类中同时都有test()方法和demo()方法。在实际使用过程中,我们的C类到底应该继承哪个父类中的方法呢?在python中有一个MRO(method resolution order)方法搜索顺序内置属性,可以通过mro查看方法的搜索顺序,主要用于在多继承时判断方法和属性的调用路径。
这里写图片描述

class A:

    def demo(self):
        print("A demo 方法")

    def test(self):
        print("A test 方法")


class B:

    def demo(self):
        print("B demo 方法")

    def test(self):
        print("Atest 方法")


class C(A, B):

    pass


c = C()
c.demo()
c.test()

# 确定C类的调用方法
print(C.__mro__)

运行上面代码输出以下信息:
这里写图片描述
表示的在执行是首先查看方法是不是在C类中,如果不是继续向下查看是否在A类中,如果还是没有便继续向下查找,如果有的话就停止查找执行找到的方法。
从上面的输出可以看到最后的object类,object类为python中所有类的基类,提供有一些内置的属性和方法,可以使用dir函数查看。

猜你喜欢

转载自blog.csdn.net/Katherine_hsr/article/details/82377643