You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript重写含装饰器的父类方法后如何获取最终方法实现

问题:子类重写装饰器修饰的父类方法后,如何获取子类的方法实现?

当前代码中,子类Child重写了父类Parent中带有装饰器@D()的doSomething方法,但通过装饰器存入对象a的doSomething方法调用时,输出的仍是父类的'parent',而非子类的'child'。请问如何获取最终的子类方法实现?

代码示例

const a = {} as any

class Parent {
    @D()
    public doSomething(b: any) {
        console.log('parent')
    }
}

class Child extends Parent{
    public override doSomething() {
        console.log('child')
    }
}

const child = new Child()
child.doSomething()

function D () {
    return function(target: any, property: string, descriptor: PropertyDescriptor) {
        console.log('assign')
        a[property] = target[property]
    }
}

setTimeout(a.doSomething, 1000)   // 此处输出"parent",期望输出"child"

问题原因

装饰器是在类定义阶段执行的:当Parent类被装饰时,D装饰器直接把Parent.prototype.doSomething的引用存到了a对象里。而子类Child重写方法是在子类定义时修改Child.prototype,这不会改变a里已经存储的父类方法引用,所以调用a.doSomething时自然输出父类的结果。

解决方案

根据使用场景,有两种常用处理方式:

方案1:通过实例动态调用(通用推荐)

修改装饰器逻辑,不直接存储方法引用,而是存储一个接收实例的代理函数。调用时传入子类实例,利用原型链查找自动获取子类的重写方法:

const a = {} as any

class Parent {
    @D()
    public doSomething(b: any) {
        console.log('parent')
    }
}

class Child extends Parent{
    public override doSomething() {
        console.log('child')
    }
}

const child = new Child()
child.doSomething()

function D () {
    return function(target: any, property: string, descriptor: PropertyDescriptor) {
        console.log('assign')
        // 存储代理函数,接收实例和参数
        a[property] = (instance: any, ...args: any[]) => {
            instance[property](...args)
        }
    }
}

// 调用时传入子类实例
setTimeout(() => a.doSomething(child), 1000)   // 输出"child"

方案2:手动更新子类方法引用(适合确定子类的场景)

如果已经明确最终会使用Child子类,可以在子类定义完成后,手动将子类原型的方法更新到a对象中:

const a = {} as any

class Parent {
    @D()
    public doSomething(b: any) {
        console.log('parent')
    }
}

class Child extends Parent{
    public override doSomething() {
        console.log('child')
    }
}

// 子类定义后,更新a中的方法引用
a.doSomething = Child.prototype.doSomething

const child = new Child()
child.doSomething()

function D () {
    return function(target: any, property: string, descriptor: PropertyDescriptor) {
        console.log('assign')
        a[property] = target[property]
    }
}

setTimeout(a.doSomething, 1000)   // 输出"child"

补充说明

  • 方案1更通用,不管后续有多少个子类重写方法,只要传入对应子类的实例就能调用到正确的方法;
  • 方案2更直接,但依赖于明确知道最终使用的子类,灵活性稍差。

内容的提问来源于stack exchange,提问作者Oki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 13:30:15