Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Classes cannot extend classes that extend classes #1529

Closed
gfwilliams opened this issue Oct 18, 2018 · 2 comments
Closed

Classes cannot extend classes that extend classes #1529

gfwilliams opened this issue Oct 18, 2018 · 2 comments

Comments

@gfwilliams
Copy link
Member

class A {
}
class B extends A {
}
class C extends B {
}
new A(); // ok
new B(); // ok
new C(); // stack overflow

Why? Because there's a default constructor that calls the constructor on the class that's been extended. That's in itself is fine.

The issue is that this is always set to the instance of C, so when the default constructor in B searches for the default constructor on the class extended by B, it always points to B's constructor instead.

It's an issue on any function in an extended class that uses super. I guess we might need to store another superThis variable that points to 'this' for the currently executing function.

@nebbishhacker
Copy link

I just ran into this bug :)

One workaround is to call the base class constructor explicitly:

class A { constructor() { this.foo = 42; } }
class B extends A { constructor() { A.call(this); } }
class C extends B { constructor() { B.call(this); } }
print(new C().foo); // prints 42

(Note that although this code works on Espruino, it isn't valid ES6 since it doesn't call super())

@gfwilliams
Copy link
Member Author

Sent in a PM to me, this has a problem too:

class Being  { 
    constructor(theLabel) {
        this.label = theLabel;
    }

    name() {
        return this.label;
    }
}

class Animal extends Being { 
    constructor(theLabel) {
        super(theLabel);
    }
}

class Dog extends Animal { 
    constructor(theLabel) {
        super(theLabel);
    }
}

class Cat extends Animal {
    constructor(theLabel) {
        super(theLabel);
    }
 }


const c = new Cat("Felix");
const d = new Dog("Fido");

console.log("Name:" + c.name());

Before, we were adding default constructor code of if(this.__proto__.__proto__.constructor)this.__proto__.__proto__.constructor.apply(this,arguments) to the constructor if it wasn't specified, and I figured I could do what @nebbishhacker had done above and explicitly reference the extended class (which works!) and fixes the original issue.

However super isn't so easy - I'm looking into it now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants