调用超级超类

时间:2018-03-01 18:28:43

标签: typescript inheritance ecmascript-6

当每个类包含一个具有相同名称的方法时,我在访问层次结构中的方法时遇到了问题。

class A { 
    constructor(private name: string) { }
    notify() { alert(this.name) }
}

class B extends A { 
    constructor() {
        super("AAA")
    }

    notify() {alert("B") }
}

class C extends B { 
    notify() { alert("C") }

    callA() {
        this.notify(); // this alerts "C"
        super.notify(); // this alerts "B"

        // How to call notify() of the class A so it alerts "AAA"? 
    }
}

new C().callA();

2 个答案:

答案 0 :(得分:3)

虽然我质疑要求您执行此操作的设计,但您可以通过获取A.prototype的原始方法并使用call轻松解决此问题:

class C extends B { 
    notify() { alert("C") }

    callA() {
        A.prototype.notify.call(this);
    }
}

答案 1 :(得分:1)

通过爬上原型链可以达到祖父母方法:

class C extends B { 
    notify() { alert("C") }

    callA() {
        this.notify(); // this alerts "C"
        const grandparentNotify = super.__proto__.notify;
        grandparentNotify.call(this); // this alerts "AAA"
    }
}

__proto__用于说明目的,因为获取对象原型的正确方法是Object.getPrototypeOf。请注意,grantparent原型的super.__proto__链在实现之间可能不同(例如TypeScript和native)。

不应该达到祖父母方法,因为这表明设计问题;孙子不应该知道祖父母的方法。在方法中使用call是类设计出错的另一个迹象。

如果需要在扩展类中使用来自另一个类的方法(它是否真的无关紧要),这应该通过mixin明确地完成。由于C并不需要所有祖父方法,并且需要避免命名冲突,因此应直接指定方法:

interface C {
    grandparentNotify(): void;
}
class C extends B { 
    notify() { alert("C") }

    callA() {
        this.notify(); // this alerts "C"
        this.grandparentNotify(); // this alerts "AAA"
    }
}
C.prototype.grandparentNotify = A.prototype.notify;

接口已合并,键入系统将grandparentNotify接受为C方法。这种方式看起来很原始,但这是分配方法的惯用方法。

提供一些开销但不需要接口合并的更平滑的方法是getter:

class C extends B { 
    notify() { alert("C") }

    get grandparentNotify() {
        return A.prototype.notify;
    }

    callA() {
        this.notify(); // this alerts "C"
        this.grandparentNotify(); // this alerts "AAA"
    }
}