【问题标题】:Calling a method of a super-super class调用超超类的方法
【发布时间】:2018-03-01 18:28:43
【问题描述】:

当每个类都包含同名的方法时,我无法访问层次结构中的方法。

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();

【问题讨论】:

  • 没有允许你这样做的结构——但你具体想做什么?覆盖方法时应始终小心。

标签: typescript inheritance ecmascript-6


【解决方案1】:

虽然我质疑要求您这样做的设计,但您可以通过获取 A.prototype 的原始方法并使用 call 轻松实现这一点:

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

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

【讨论】:

    【解决方案2】:

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

    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。请注意,授予父原型的 super.__proto__ 链可能在不同的实现(例如 TypeScript 和原生)之间有所不同。

    不应该达到祖父方法,因为这表明设计问题;孙子不应该知道祖父母的方法。在方法中使用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"
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-03-28
      • 2012-12-30
      • 2015-04-20
      • 2021-11-10
      • 1970-01-01
      • 1970-01-01
      • 2014-01-15
      • 1970-01-01
      • 2012-09-02
      相关资源
      最近更新 更多