在面向对象编程中,方法重写和 super()
函数是实现继承和多态的关键技术。它们允许子类扩展或修改父类的行为,同时保持代码的复用性和灵活性。
一、方法重写(Method Overriding)
1. 什么是方法重写?
方法重写是指子类重新定义从父类继承的方法,以提供特定实现的过程。这是实现多态的核心机制。
核心概念:
2. 基本语法
class Parent:
def method(self):
print("父类方法")
class Child(Parent):
def method(self): # 重写父类方法
print("子类方法")
# 使用
obj = Child()
obj.method() # 输出: 子类方法
3. 重写规则
方法签名一致:
# 正确重写
classParent:
defcalculate(self, a, b):
return a + b
classChild(Parent):
defcalculate(self, a, b): # 参数相同
return a * b
# 错误重写(参数不同)
classWrongChild(Parent):
defcalculate(self, a): # 缺少参数
return a * 2
访问权限:
- 不能降低方法的可见性(如父类public方法在子类中不能变为private)
特殊方法重写:
class Vector:
def__init__(self, x, y):
self.x = x
self.y = y
def__str__(self):
returnf"({self.x}, {self.y})"
classVector3D(Vector):
def__init__(self, x, y, z):
super().__init__(x, y)
self.z = z
def__str__(self): # 重写字符串表示
returnf"({self.x}, {self.y}, {self.z})"
v = Vector3D(1, 2, 3)
print(v) # (1, 2, 3)
super()
用于调用父类(超类)的方法,实现扩展而非完全替代父类功能。
1. 基本用法
class Parent:
def__init__(self, name):
self.name = name
defgreet(self):
print(f"你好,我是{self.name}")
classChild(Parent):
def__init__(self, name, age):
super().__init__(name) # 调用父类构造方法
self.age = age
defgreet(self):
super().greet() # 调用父类方法
print(f"我今年{self.age}岁")
# 使用
child = Child("小明", 10)
child.greet()
# 输出:
# 你好,我是小明
# 我今年10岁
2. super() 的工作原理
super()
返回一个代理对象,它会按照方法解析顺序(MRO)查找方法。
MRO 示例:
class A:
defmethod(self):
print("A的方法")
classB(A):
defmethod(self):
print("B的方法")
super().method()
classC(A):
defmethod(self):
print("C的方法")
super().method()
classD(B, C):
defmethod(self):
print("D的方法")
super().method()
# 查看MRO
print(D.mro()) # [D, B, C, A, object]
# 调用
d = D()
d.method()
# 输出:
# D的方法
# B的方法
# C的方法
# A的方法
3. super() 的两种形式
单参数形式:super().method()
双参数形式:super(class, object).method()
class Base:
defmethod(self):
print("Base method")
classDerived(Base):
defmethod(self):
print("Derived start")
super(Derived, self).method() # 显式指定
print("Derived end")
d = Derived()
d.method()
适用场景:
1. 扩展父类方法
class Logger:
deflog(self, message):
print(f"日志: {message}")
classTimestampLogger(Logger):
deflog(self, message):
import datetime
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
super().log(f"[{timestamp}] {message}") # 添加时间戳
# 使用
logger = TimestampLogger()
logger.log("系统启动") # 日志: [2023-07-20 14:30:00] 系统启动
2. 修改方法行为
class PaymentProcessor:
defprocess_payment(self, amount):
print(f"处理支付: ${amount:.2f}")
# 实际支付逻辑...
classFraudDetectionProcessor(PaymentProcessor):
defprocess_payment(self, amount):
if amount > 10000:
print("警告: 大额支付需要人工审核")
self.manual_review(amount)
else:
super().process_payment(amount) # 正常处理
defmanual_review(self, amount):
print(f"人工审核中... ${amount:.2f}")
# 使用
processor = FraudDetectionProcessor()
processor.process_payment(500) # 正常处理
processor.process_payment(15000) # 触发人工审核
3. 协同多重继承
class Animal:
def__init__(self, name):
self.name = name
classFlyer:
def__init__(self, max_altitude):
self.max_altitude = max_altitude
deffly(self):
print(f"飞行高度: {self.max_altitude}米")
classBird(Animal, Flyer):
def__init__(self, name, max_altitude):
# 调用多个父类的构造方法
Animal.__init__(self, name)
Flyer.__init__(self, max_altitude)
defdescribe(self):
print(f"{self.name} 能飞到 {self.max_altitude}米高")
# 使用
eagle = Bird("老鹰", 3000)
eagle.describe()
eagle.fly()
问题1:忘记调用 super()
错误示例:
class Base:
def __init__(self):
self.base_value = 10
class Derived(Base):
def __init__(self):
self.derived_value = 20 # 忘记调用super()
d = Derived()
print(d.base_value) # AttributeError!
解决方案:
class Derived(Base):
def __init__(self):
super().__init__() # 正确调用
self.derived_value = 20
问题2:错误的方法签名
错误示例:
class Shape:
def draw(self, color):
print(f"绘制{color}的图形")
class Circle(Shape):
def draw(self): # 缺少参数
super().draw("红色") # 硬编码颜色
解决方案:
class Circle(Shape):
def draw(self, color="红色"): # 保持参数兼容
super().draw(color) # 正确传递参数
问题3:多重继承中的钻石问题
解决方案: Python 使用 C3 线性化算法确定 MRO:
class Base:
defmethod(self):
print("Base")
classLeft(Base):
defmethod(self):
print("Left-start")
super().method()
print("Left-end")
classRight(Base):
defmethod(self):
print("Right-start")
super().method()
print("Right-end")
classDerived(Left, Right):
defmethod(self):
print("Derived-start")
super().method()
print("Derived-end")
d = Derived()
d.method()
"""
输出:
Derived-start
Left-start
Right-start
Base
Right-end
Left-end
Derived-end
"""
一致的重写:
合理使用 super():
- 在构造方法中始终调用
super().__init__()
避免多重继承陷阱:
测试覆盖:
import unittest
classTestChild(unittest.TestCase):
deftest_method_override(self):
child = Child()
child.method() # 测试重写方法
# 验证输出或状态
deftest_super_call(self):
with patch('__main__.Parent.method') as mock_parent:
child = Child()
child.greet()
mock_parent.assert_called_once() # 验证super调用
要点:
super()
- 重写构造方法时必须调用
super().__init__()
- 多重继承中使用
super()
遵循 MRO 顺序
"好的继承设计不是关于代码复用,而是关于创建可维护、可扩展的抽象层次结构。方法重写和super()是实现这一目标的关键工具。"
阅读原文:原文链接
该文章在 2025/7/18 10:48:42 编辑过