TypeScript - 如何继承类并覆盖 lambda 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38640961/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:41:52  来源:igfitidea点击:

TypeScript - how to inherit class and override lambda method

javascriptinheritancetypescriptlambda

提问by user210757

I have an inherited class, and need the parent to have a virtual method, which is overridden in the child class. This method is called from the base constructor, and needs access to instance properties, so it needs to be a lambda function, so "this" is "_this". The problem is, overriding a lambda method does not work for me like overriding a non-lambda does. Is this possible? If not, I'd like to understand why.

我有一个继承的类,并且需要父类有一个虚拟方法,该方法在子类中被覆盖。这个方法是从基础构造函数调用的,需要访问实例属性,所以它需要是一个lambda函数,所以“this”就是“_this”。问题是,覆盖 lambda 方法对我不起作用,就像覆盖非 lambda 方法一样。这可能吗?如果没有,我想了解原因。

Also, will "this" always be the same as "_this" when the method is only called from the constructor?

此外,当该方法仅从构造函数调用时,“this”是否始终与“_this”相同?

class Base {
    protected prop = null;
    constructor() {
        this.init();
        this.initLambda();
    }
    init() {
        console.log("Base init");
    }
    initLambda = () => {
        console.log("Base initLambda");
    }
}
class Derived extends Base {
    constructor() {
        super();
    }
    init() {
        console.log("Derived init");
    }
    initLambda = () => {
        //let x = this.prop;
        console.log("Derived initLambda");
    }
}

Output:
Derived init
Base initLambda

输出:
派生的 init
Base initLambda

回答by Nitzan Tomer

Well, you can't have that.
There's an issue that was openedbut it was closed as "by design".

好吧,你不能有那个。
一个问题已打开,但已作为“设计使然”关闭。

You should use regular methods:

您应该使用常规方法:

class Base {
    protected prop = null;

    constructor() {
        this.init();
        this.initLambda();
    }

    init() {
        console.log("Base init");
    }

    initLambda() {
        console.log("Base initLambda");
    }
}

class Derived extends Base {
    constructor() {
        super();
    }

    init() {
        console.log("Derived init");
    }

    initLambda() {
        console.log("Derived initLambda");
    }
}

And then it will work.

然后它会起作用。

As for keeping the right this, you can always pass a call to the method as an arrow function:

至于保持 right this,您始终可以将对该方法的调用作为箭头函数传递:

doit() {
    setTimeout(() => this.init(), 1);
}

Or use the Function.prototype.bindfunction:

或者使用Function.prototype.bind函数:

setTimeout(this.init.bind(this));

Also, the _thisthing that the typescript compiler produces is just a hack to polyfil the arrow functions for ES5, but if you change the target to ES6 then it won't use it.

此外,_this打字稿编译器产生的东西只是对 ES5 箭头函数的一种 hack,但是如果您将目标更改为 ES6,则它不会使用它。



Edit:

编辑:

You can save the bound methods as members:

您可以将绑定方法保存为成员:

class Base {
    ...
    public boundInit: () => void;

    constructor() {
        ...
        this.boundInit = this.initLambda.bind(this);
        setTimeout(this.boundInit, 500);
    }

...

With that, when I do new Derived()this is what I get:

有了这个,当我这样做时new Derived(),我得到的是:

Derived init
Derived initLambda // after 200 millis

Derived init
Derived initLambda // 200 毫秒后

回答by Bruno Grieder

The problem is that your lambda is a property.

问题是你的 lambda 是一个属性。

When compiled to javascript, the Baseclass becomes

当编译为 javascript 时,Base该类变为

var Base = (function () {
    function Base() {
        this.prop = null;
        this.initLambda = function () {
            console.log("Base initLambda");
        };
        this.init();
        this.initLambda();
    }
    Base.prototype.init = function () {
        console.log("Base init");
    };
    return Base;
}());

As you can see initLambdais defined insidethe constructor of Base, so there is no way you can override that.

如您所见,它initLambda的构造函数中定义的Base,因此您无法覆盖它。

Calling super()calls the Baseconstructor which defines the this.initLambdawith the code in Baseand runs it. Hence your result.

Callingsuper()调用Base定义this.initLambda了代码的构造函数Base并运行它。因此你的结果。

View on playground

操场上观看