TypeScript如何实现子类密封已重写方法、禁止孙类重写的功能
TypeScript 目前没有原生支持类似 C# 的 override sealed 语法,可通过以下两种方案实现同等约束:
方案1:运行时强制校验
直接在 B 类的构造函数中加入重写检查,只要子类重写了 foo 方法,实例化时就会抛出错误:
abstract class A { public abstract foo(): void; } abstract class B extends A { public override foo() { // B 自身的 foo 实现逻辑 console.log('B 类的 foo 执行逻辑'); } constructor() { super(); // 校验 foo 方法是否被重写 if (this.foo !== B.prototype.foo) { throw new Error('禁止重写 B 类的 foo 方法'); } } } class CofB extends B { // 此处如果重写 foo 方法,实例化 CofB 时会直接抛出错误 } class XofA extends A { // 直接继承 A 的子类仍然可以正常重写 foo public override foo() { console.log('XofA 自定义的 foo 逻辑'); } }
- 优点:100% 拦截所有非法重写,逻辑简单不需要调整现有设计
- 缺点:仅在运行时触发,编译阶段不会提前报错
方案2:编译期约束(推荐)
调整类设计,遵循组合优于继承的思路,将 B 类中可扩展的逻辑与固定逻辑拆分,从设计层面避免子类重写 foo 的可能:
abstract class A { public abstract foo(): void; } abstract class B extends A { // foo 方法直接实现固定逻辑,不开放给子类重写 public final foo() { // B 类固定的 foo 主逻辑 this.beforeFooHook(); // 核心执行逻辑 this.afterFooHook(); } // 把允许子类自定义的逻辑抽成单独的钩子方法 protected abstract beforeFooHook(): void; protected abstract afterFooHook(): void; } class CofB extends B { // 子类只能重写钩子方法自定义扩展逻辑,无法修改 foo 主流程 protected override beforeFooHook() { // 自定义前置逻辑 } protected override afterFooHook() { // 自定义后置逻辑 } } class XofA extends A { // 直接继承 A 的子类仍然可以正常重写 foo public override foo() {} }
- 优点:无运行时额外开销,编译期就能避免错误写法,符合面向对象设计规范
- 缺点:需要对现有类的结构做少量调整
如果需要更严格的编译期提示,还可以配合 ESLint 自定义规则,禁止所有继承自 B 的类重写 foo 方法。
内容的提问来源于stack exchange,提问作者Mahdi Ghiasi
相关产品推荐
相关产品推荐

