Extending base class methods with multiple levels of inheritance (typescript)

前端 未结 2 1272
长情又很酷
长情又很酷 2021-02-19 06:48

I have 3 classes:

class A{
    DoStuff(){
        return \"Called from A\";
    }
}

class B extends A {

    constructor(){
        super();
        var baseDo         


        
相关标签:
2条回答
  • 2021-02-19 06:59

    JavaScript doesn't really have methods. TypeScript tries to hide the workings of the prototype chain with familiar notation but like all abstractions it's imperfect. The gist of the prototype chain is that when you call c.DoStuff() it looks for DoStuff on the c instance, than the prototype (C), then its prototype (B), then its prototype (A), and then its prototype (Object).

    That applies not just to functions but to any member you might look up. Functions aren't very special in JavaScript, which ironically is what makes them powerful.

    Using TypeScript's syntax in your A class you're putting a function DoStuff in A's prototype. Every instance of A you call DoStuff on will look for it in the instance (and probably failing to find it there) look at the prototype and see that function you defined. So far so good.

    Then you defined a class B which extends A, so the prototype chain is B->A->Object. Inside the constructor of B you assign a new copy of a function to DoStuff on every single instance. (This uses a lot more memory.) So when you construct a new B and call DoStuff on it, there's a function there without ever examining the prototype. So that works.

    Now you define a class C extending B and the prototype chain is C->B->A->Object. Again every instance of C gets a copy of a function assigned to DoStuff. But inside that constructor we're not grabbing DoStuff from an instance of B, we're grabbing it from the prototype, and we didn't add that function directly to the prototype. Failing to find it there we go up the prototype chain to A.prototype and find a DoStuff member to use from there. That's why C has a reference to A's DoStuff.

    You could make your code work as expected if you did something like this:

    class B extends A {
        constructor() {
            super();
        }
    }
    B.prototype.DoStuff = function () {
        return A.prototype.DoStuff() + " and Called from B";
    }
    

    But that's just being silly.

    0 讨论(0)
  • 2021-02-19 07:00

    Whenever you need to use super Use class methods instead of class members:

    class A{
        DoStuff(){
            return "Called from A";
        }
    }
    
    class B extends A {
    
        constructor(){
            super();      
    
        }   
        DoStuff (){
            return super.DoStuff() + " and Called from B";
        }
    }
    
    class C extends B { 
        constructor(){
            super();                
        }
    
        DoStuff(){
                return super.DoStuff() + " and Called from C";
        }
    }
    
    var c = new C();
    console.log(c.DoStuff());
    

    Try it (prints Called from A and Called from B and Called from C)

    This is because super translates to .prototype i.e. super.DoStuff() becomes _super.prototype.DoStuff() and the only things available on .prototype are class methods.

    More: http://basarat.github.io/TypeScriptDeepDive/#/super

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