在面向对象编程中,方法重写和 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 编辑过