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

I have 3 classes:

class A{ DoStuff(){ return "Called from A"; } } class B extends A { constructor(){ super(); var baseDoStuff = super.DoStuff; this.DoStuff = function(){ return baseDoStuff() + " and Called from B"; } } } class C extends B { constructor(){ super(); var baseDoStufffff = super.DoStuff; this.DoStuff = function(){ return baseDoStufffff() + " and Called from C"; } } } 

I expected class C DoStuff () to call B DoStuff () (which in turn will call A).

However, calling DoStuff () on C returns only "Called from A and C from C". What am I doing wrong here? Should this method call B too?

A working example of this can be found here:

Example

+7
source share
2 answers

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

 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 (fingerprints called from A and called from B and called from C)

This is because super translates to .prototype ie super.DoStuff() becomes _super.prototype.DoStuff() , and the only things available in .prototype are class methods.

More details: http://basarat.imtqy.com/TypeScriptDeepDive/#/super

+9
source

There are no methods in JavaScript. TypeScript tries to hide the work of the prototype with the familiar notation, but, like all abstractions, it is imperfect. The essence of the prototype chain is that when c.DoStuff() is called, it searches for DoStuff in instance c than prototype (C), then its prototype (B), then its prototype (A), and then its prototype (Object).

This applies not only to functions, but to any member that you can find. Functions are not very specific in JavaScript, which, ironically, makes them powerful.

Using the TypeScript syntax in your class A, you put the DoStuff function in prototype A. Each instance of A that you call DoStuff on will look for it in the instance (and probably won't find it there), look at the prototype and see which function you have identified. So far so good.

Then you define a class B that extends A, so the prototype chain is B-> A-> Object. Inside Constructor B, you assign a new copy of the DoStuff function to each individual instance. (This uses a lot more memory.) Therefore, when you build a new B and call DoStuff on it, there is a function that does not parse the prototype. So that works.

Now you define a class C extending B, and the prototype chain C-> B-> A-> Object. Again, each C instance receives a copy of the function assigned by DoStuff. But inside this constructor, we do not grab the DoStuff from instance B, we grab it from the prototype, and we did not add this function directly to the prototype. Not finding it there, we will go up the prototype chain to A.prototype and find the DoStuff member to use from there. Therefore, C has a link to A DoStuff.

You can get your code to 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 is just plain stupid.

+5
source

All Articles