I’m super stumped. I want to create a family of objects that all share common properties, but don’t share methods. I would like
class X { x: any; myFunc() { console.log(this.x); } constructor() { this.x = true; this.myFunc(); } } class Y extends X { y: any; myFunc() { console.log(this.y); } constructor() { super(); this.y = 2; this.myFunc(); } } class Z extends Y { z: any; myFunc() { console.log(this.z); } constructor() { super(); this.z = "something stupid"; this.myFunc(); } } new Z(); // should print // true // 2 // something stupid new Y(); // should print // true // 2 new X(); // should print // true
The current behavior is for new Z()
to print something stupid
3 times.
I would like a way to call a method inside a class that isn’t overridden, but calls outside are. In C++, you can define a virtual public method and a private non-virtual method, and I would like to replicate something like that.
Advertisement
Answer
Update in response to your comments and new question information:
It seems like you want a combination of override (public) methods and private (method) fields:
class X { x: any; #fn() { console.log(this.x); } fn() { this.#fn(); } constructor() { this.x = true; this.#fn(); } } class Y extends X { y: any; #fn() { console.log(this.y); } override fn() { this.#fn(); } constructor() { super(); this.y = 2; this.#fn(); } } class Z extends Y { z: any; #fn() { console.log(this.z); } override fn() { this.#fn(); } constructor() { super(); this.z = "something stupid"; this.#fn(); } } const z = new Z(); // true, 2, "something stupid" z.fn(); // "something stupid" const y = new Y(); // true, 2 y.fn(); // 2 const x = new X(); // true x.fn(); // true
Original answer:
You can do it by extending each of them from the same abstract class rather extending each from the previous. If you’re extending each from the previous for the purpose of instantiation side-effects, then extension is probably not the optimal pattern, but I can’t make another suggestion without a more concrete explanation of the problem:
abstract class C { abstract myFunc (): void; } class X extends C { x: any; myFunc() { console.log("x"); } constructor() { super(); this.x = true; this.myFunc(); } } class Y extends C { y: any; myFunc() { console.log("y"); } constructor() { super(); this.y = 2; this.myFunc(); } } class Z extends C { z: any; myFunc() { console.log("z"); } constructor() { super(); this.z = "something stupid"; this.myFunc(); } } new Z(); // logs "z"
Note that, other than the nominal inheritance of the abstract class, this pattern is no different than implement
ing from an interface:
interface C { myFunc (): void; } class X implements C { x: any; myFunc() { console.log("x"); } constructor() { this.x = true; this.myFunc(); } } class Y implements C { y: any; myFunc() { console.log("y"); } constructor() { this.y = 2; this.myFunc(); } } class Z implements C { z: any; myFunc() { console.log("z"); } constructor() { this.z = "something stupid"; this.myFunc(); } } new Z(); // logs "z"