问题: 子类继承父类后,如何重写父类的方法?

👇 点击展开/折叠 面试背诵模板(建议先背这个) 子类通过定义与父类同名的方法即可完成重写(Override),从而覆盖父类原有行为。若需保留并扩展父类逻辑,使用 super().方法名() 调用父类方法;若不调用则完全替换。重写 __init__ 时必须调用 super().__init__(),否则父类属性缺失,访问时报 AttributeError。参数列表建议与父类保持一致(符合里氏替换原则),Python 虽允许修改但不推荐,会破坏多态性。Python 3.12+ 可用 from typing import override 装饰器,让类型检查器验证父类确有同名方法。
---

重写的两种模式:完全替换与扩展增强

  • 完全替换:子类方法不调用父类方法,所有逻辑重新定义,适用于父类行为完全不适用。
  • 扩展增强:子类方法先调用 super().方法() 获取父类结果,再追加额外逻辑,遵循开闭原则。
1
2
3
4
5
6
7
8
9
10
11
class Animal:
def speak(self):
return "动物声音"

class Dog(Animal):
def speak(self): # 完全替换
return "汪汪叫"

class Cat(Animal):
def speak(self): # 扩展增强
return f"{super().speak()} + 喵喵叫"

重写 __init__ 的强制约束与执行顺序

子类重写 __init__ 时,父类的实例属性不会被自动继承,必须显式调用 super().__init__() 触发父类初始化。调用位置通常放在子类初始化逻辑的最前面,确保父类属性先建立,子类属性后附加,避免覆盖冲突。

1
2
3
4
5
6
7
8
class Parent:
def __init__(self, name):
self.name = name

class Child(Parent):
def __init__(self, name, age):
super().__init__(name) # 必须优先调用
self.age = age # 子类特有属性

参数列表修改的多态性风险

Python 语法允许子类重写方法时增减参数(如 def speak(self, loud=False)),但会导致多态失效。当通过父类引用调用时(实际传入子类实例),参数不匹配会抛出异常。日常开发中,只要涉及多态场景(如列表 [Dog(), Cat()] 循环调用),重写方法应严格保持参数类型和数量与父类一致。

强制子类必须重写的方法(抽象方法)

若父类方法无合理默认实现,可使用 @abstractmethod 强制子类重写,否则子类无法实例化。这属于“契约式设计”,将“做什么”与“怎么做”分离。

1
2
3
4
5
6
7
8
9
10
from abc import ABC, abstractmethod

class Payment(ABC):
@abstractmethod
def pay(self, amount):
pass

class WechatPay(Payment):
def pay(self, amount): # 必须实现,否则报错
print(f"微信支付 {amount}")