TLDR; How to directly call setter of an object's parent class without invoking the child's setter outside of both the parent and child class?
I know that if the solution exists, it may be very hacky/magic-like, but I don't mind. Here's the scenario:
Parent is class from a 3rd party library so I can't change this code at all.Child is a class from my codebase, but I'd like to keep the magic code outside of it, as the Prop class may be use with different "Child" classes.Prop is the class where the magic code may reside if necessary.I need to access the Parent's setter of x via a Child object without invoking the setter of x of the Child.
Is it even possible?
class Parent {
constructor() {
this._x = 255;
}
set x(v) {
console.log("Calling Parent setter");
this._x = v;
}
get x() {
console.log("Calling Parent getter");
return this._x;
}
}
class Child extends Parent {
constructor() {
super();
this.prop = new Prop(this);
}
set x(v) {
console.log("AVOID! Calling Child setter");
super.x = v;
// Shennanigans I don't want to run
}
get x() {
console.log("Calling Child getter");
return super.x;
}
}
class Prop {
constructor(child) {
this.child = child;
}
setX() {
const parent = this.child; // Not sure what to do here.
const old = parent.x;
parent.x = 0;
console.log(`parent.x changed from ${old} to ${parent.x}`);
}
}
const child = new Child();
child.prop.setX();
Reflect.set is here to your rescue! It does allow to pass the receiver separately:
setX() {
Reflect.set(Parent.prototype, "x", 0, this.child); // invokes the Parent.protype.x setter
}
Alternatives would be Object.getOwnPropertyDescriptor(Parent.prototype, "x").set.call(this.child, 0) or just this.child._x = 0 (if you don't need to run the setter code).
So while it is possible, I would recommend to reconsider your design. Maybe inheritance is the wrong approach here, and you should use composition instead of extends Parent:
class Child {
constructor() {
this.val = new Parent();
}
set x(v) {
… // Shenanigans
this.val.x = v;
}
get x() {
return this.val.x;
}
// (without the Prop helper class for simplicity)
setX(v) {
// without shenanigans
this.val.x = v;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With