前置知识
- 继承的详解:https://www.cnblogs.com/poloyy/p/15216652.html
- 子类方法的重写:https://www.cnblogs.com/poloyy/p/15221352.html
- 多继承的详解:https://www.cnblogs.com/poloyy/p/15224912.html
为什么要用 super()
当子类重写了父类方法时,又想调用父类的同名方法时,就需要用到 super()
什么是 super
- 在 Python 中,super 是一个特殊的类
- super() 就是使用 super 类创建出来的对象
- 实际应用的场景:子类在重写父类方法时,调用父类方法
单继承中使用 super
实例方法使用 super
类图
实际代码
class A: def __init__(self): self.n = 1 def add(self, m): print(f'AAA [self] is {id(self)}') print(f'AAA [self.n] is {self.n}') self.n += m class B(A): def __init__(self): self.n = 100 # 重写父类方法 def add(self, m): # 子类特有代码 print(f'BBB [self] is {id(self)}') print(f'BBB [self.n] is {self.n}') # 调用父类方法 super().add(m) self.n += m b = B() b.add(2) print(b.n) # 输出结果 BBB [self] is 4489158560 BBB [self.n] is 100 AAA [self] is 4489158560 AAA [self.n] is 100 104
- super().add() 的确调用了父类方法
- 重点:此时父类方法的 self 并不是父类实例对象,而是子类实例对象
构造方法使用 super
class Animal: def __init__(self, name): self.name = name def prints(self): print("Animale name is ", self.name) class Dog(Animal): def __init__(self, name, age): # 调用父类的 init 构造方法 super(Dog, self).__init__(name) self.age = age def prints(self): # 调用父类的方法 super(Dog, self).prints() print("Dog age is ", self.age) dog = Dog("小汪", 10) dog.prints() # 输出结果 Animale name is 小汪 Dog age is 10
这里用了 super(子类名, self) ,和上面的 super() 是一样效果
调用父类方法有两种方式
- super().父类方法() :注意,只能在 Python 3.x 中使用
- super(子类名, self).父类方法()
其实还有第三种
在 Python 2.x 的时候,如果需要调用父类的方法,还可以用
父类名.方法(self)
- 这种方式,Python 3.x 还是支持的
- 不过不推荐,因为父类名发生变化的话,方法调用位置的类名也要同步修改
通过父类名调用父类方法(不推荐)
class Animal: def __init__(self, name): self.name = name def prints(self): print("Animale name is ", self.name) class Dog(Animal): def __init__(self, name, age): # 调用父类的 init 构造方法 Animal.__init__(self, name) self.age = age def prints(self): # 调用父类的方法 Animal.prints(self) print("Dog age is ", self.age) dog = Dog("小汪", 10) dog.prints() # 输出结果 Animale name is 小汪 Dog age is 10
通过父类名调用的这种方式,是需要传 self 参数的哦
温馨提示
在开发时, 父类名.方法() , super().方法() 两种方式不要混用哈
灵魂拷问一:既然已经重写了子类的构造方法,为什么还要去调用 super?
子类需要重写父类方法来实现子类独有的功能,但同时又需要依赖父类方法来完成某些逻辑
实际栗子
- 在实现多线程的时候(后面会详细展开说多线程)
- 父类 Thread 的构造方法包含了很多逻辑代码
- 子线程虽然需要实现子类独有功能,但仍需父类方法来处理其他逻辑