Python继承中的方法重写(方法的覆盖、父类方法扩展)

在继承中,子类拥有父类所有的属性和方法,可以直接使用父类中已经封装好的方法,但如果父类中的方法不能满足子类需求,就要在子类中对方法进行重写。

如果子类与父类的方法和属性名相同,则在使用子类对象进行调用时,默认调用的是子类中定义的属性和方法。

方法重写分为两种情况:

1、覆盖父类的方法

父类与子类的方法实现完全不同,可以使用覆盖的方式,就是在子类中重新编写父类的方法实现。相当于在子类中定义了一个和父类同名的方法并实现。

重写之后,在使用子类对象调用方法时,只会调用子类中重写的方法,而不会调用父类中封装的方法。

class Pig:
    def hobby(self):
        print('小猪喜欢吃东西和睡觉')


class Peppa(Pig):  # Peppa类继承自Pig类
    def hobby(self):
        print('佩奇最喜欢跳泥坑')


pig = Pig()
# 父类的hobby方法
pig.hobby()  # 小猪喜欢吃东西和睡觉

peppa = Peppa()
# 子类Peppa对父类Pig中的hobby方法进行了重写,所以调用的是子类Peppa的hobby方法
peppa.hobby()  # 佩奇最喜欢跳泥坑
图片[1]-Python继承中的方法重写(方法的覆盖、父类方法扩展)-尤尤'blog

2、对父类的方法进行扩展

如果父类原本封装的方法实现是子类方法的一部分(子类方法的实现包含父类的方法实现),就可以使用扩展的方式来实现:在需要的位置使用 super().父类方法 来调用父类的方法,然后在其他位置针对子类的需求,编写子类特有的代码实现。

覆盖是在子类中对父类的方法实现完全修改了,扩展是在子类中对父类的方法实现增加了一些功能。

class Pig:
    def hobby(self):
        print('小猪喜欢吃东西和睡觉')


class Peppa(Pig):  # 子类
    def hobby(self):  # 对父类的hobby方法进行扩展
        # 针对子类的需求,编写子类特有的
        print('我是小猪佩奇。')
        # 使用super().父类方法,调用原本在父类中封装的方法
        super().hobby()
        print('佩奇最喜欢跳泥坑')


pig = Pig()
# 父类的hobby方法
pig.hobby()  # 小猪喜欢吃东西和睡觉

peppa = Peppa()
# 子类Peppa对父类Pig中的hobby方法进行了重写,所以调用的是子类Peppa的hobby方法
peppa.hobby()  # 佩奇最喜欢跳泥坑
图片[2]-Python继承中的方法重写(方法的覆盖、父类方法扩展)-尤尤'blog

这里涉及一个 super,下面介绍一下:

调用父类的方法 —— super类

super 是 Python 中的一个特殊的类。super() 就是实例化了一个 super 类,就像一个 Person 类,使用 “Person()” 实例化一个对象。

它通常用于在重写父类方法时,调用在父类中封装的方法实现。

调用方法:super(子类名,self).方法名(参数1,参数2……)。其中 子类名,self 这两个参数可以省略。

语法格式:

# 1、有参数
super(当前子类名,self).方法名(参数1,参数2……)

# 2、省略参数
super().方法名(参数1,参数2……)
子类必须在其构造函数中调用父类的构造函数

如果父类定义了 __init__() 方法,而子类没有定义,则默认子类继承父类的 __init__() 方法。如果子类也定义了 __init__() 方法,那就是子类重写了父类的 __init__() 方法。一般就是对父类 __init__() 方法进行扩展,所以在子类的构造函数中,要调用父类的构造函数 __init__()。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def printInfo(self):
        print(f'我的名字叫{self.name},今年{self.age}岁。')


class Student(Person):
    # 子类必须在其构造函数中调用父类的构造函数
    def __init__(self, name, age, stu_id):
        super().__init__(name, age)  # 调用父类的__init__()方法
        self.stu_id = stu_id  # 增加子类特有的属性

    def printInfo(self):  # 父类的printInfo方法不能满足子类的需求,所以对方法进行重写扩展
        # super(子类名,self).方法名(参数1,参数2……)。其中 子类名,self 这两个参数可以省略。
        super().printInfo()
        print(f'我的学号是{self.stu_id}')


class Teacher(Person):
    # 父类Person定义了__init__()方法,子类需显式调用父类的__init__方法
    def __init__(self, name, age, teacher_yaear):
        # super(子类名,self).方法名(参数1,参数2……)。其中 子类名,self 这两个参数可以省略。
        # super(Teacher,self).__init__(name, age)  # 调用父类的__init__()方法
        super().__init__(name, age)  # 调用父类的__init__()方法

        self.teacher_yaear = teacher_yaear  # 增加子类特有的属性

    def printInfo(self):  # 父类的printInfo方法不能满足子类的需求,所以对方法进行重写扩展
        print(f'我的名字叫{self.name},今年{self.age}岁,我的教龄是{self.teacher_yaear}')


stu = Student('张三', 21, '123456')
tea = Teacher('李老师', 45, 15)

stu.printInfo()
tea.printInfo()
图片[3]-Python继承中的方法重写(方法的覆盖、父类方法扩展)-尤尤'blog

调用父类的方法还可以通过 父类名.方法(self) 。但是这种方法不推荐使用,因为如果父类一旦发生变化,方法调用处的类名也需要修改。注意这里的类名不能写错,如果写成了当前子类名,会导致递归调用,形成死循环。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def printInfo(self):
        print(f'我的名字叫{self.name},今年{self.age}岁。')


class Student(Person):
    # 子类必须在其构造函数中调用父类的构造函数
    def __init__(self, name, age, stu_id):
        Person.__init__(self,name,age)    # 通过 父类名.方法(self) 的方式调用父类的__init__()方法
        self.stu_id = stu_id  # 增加子类特有的属性

    def printInfo(self):  # 父类的printInfo方法不能满足子类的需求,所以对方法进行重写扩展
        Person.printInfo(self)
        print(f'我的学号是{self.stu_id}')


stu = Student('张三', 21, '123456')
stu.printInfo()
图片[4]-Python继承中的方法重写(方法的覆盖、父类方法扩展)-尤尤'blog

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容