TypeScript - how to inherit class and override lambda method

后端 未结 2 1762
醉酒成梦
醉酒成梦 2020-12-19 02:06

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 a

相关标签:
2条回答
  • 2020-12-19 02:29

    The problem is that your lambda is a property.

    When compiled to javascript, the Baseclass becomes

    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 initLambda is defined inside the constructor of Base, so there is no way you can override that.

    Calling super() calls the Base constructor which defines the this.initLambda with the code in Base and runs it. Hence your result.

    View on playground

    0 讨论(0)
  • 2020-12-19 02:44

    Well, you can't have that.
    There's an issue that was opened but 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:

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

    Or use the Function.prototype.bind function:

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

    Also, the _this thing 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.


    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:

    Derived init
    Derived initLambda // after 200 millis

    0 讨论(0)
提交回复
热议问题