使用final_class的final装饰器为何无法阻止子类重写方法?
问题分析与解决:final_class的@final装饰器不限制方法重写
核心问题:你误解了final_class包的@final作用范围
final_class包提供的@final装饰器仅用于标记类为final,禁止类被继承,它没有实现对方法的final限制逻辑。当你把它用在方法上时,这个装饰器不会执行任何阻止子类重写的操作,所以子类可以正常重写该方法,运行时也不会报错。
验证方式
你可以测试标记final类的场景,此时会触发预期的禁止继承错误,说明该装饰器的设计目标仅针对类:
from final_class import final @final class Dummy: pass class Demo(Dummy): # 此处直接报错,因为Dummy是final类 pass
实现方法级final限制的方案
如果需要让方法无法被子类重写,可以通过以下几种方式实现:
1. 自定义方法final装饰器+子类检查
自己实现一个装饰器标记方法为final,然后在子类定义时主动检查是否重写了final方法:
def final_method(func): # 给方法添加标记,标识为final func._is_final = True return func class Dummy: def show(self): print("show is running from dummy") @final_method def display(self): print("display from dummy") class Demo(Dummy): def show(self): print("show from demo") def display(self): print("display from demo") # 检查子类是否重写了final方法 for method_name in Demo.__dict__: parent_method = Dummy.__dict__.get(method_name) if parent_method and hasattr(parent_method, "_is_final"): raise TypeError(f"无法重写final方法: {method_name}") d = Demo() d.display()
2. 利用父类的__init_subclass__自动检查
通过父类的__init_subclass__钩子,在子类创建时自动校验是否重写了final方法:
def final_method(func): func._is_final = True return func class Dummy: def __init_subclass__(cls): # 遍历子类的方法,检查是否重写了父类的final方法 for method_name, method in cls.__dict__.items(): parent_method = super().__dict__.get(method_name) if parent_method and hasattr(parent_method, "_is_final"): raise TypeError(f"类 {cls.__name__} 不能重写final方法 {method_name}") def show(self): print("show is running from dummy") @final_method def display(self): print("display from dummy") # 定义子类时会直接报错 class Demo(Dummy): def show(self): print("show from demo") def display(self): print("display from demo")
3. 使用静态类型检查工具(非运行时限制)
Python标准库typing模块的@final注解可以配合mypy等静态检查工具,在代码编写阶段提示重写final方法的错误,但不会在运行时阻止:
from typing import final class Dummy: def show(self): print("show is running from dummy") @final def display(self): print("display from dummy") class Demo(Dummy): def show(self): print("show from demo") def display(self): # mypy会提示错误:Cannot override final attribute "display" print("display from demo")
内容的提问来源于stack exchange,提问作者Kunal Rai
相关产品推荐
相关产品推荐

