Как напрямую вызвать сеттер родительского класса объекта? - PullRequest
0 голосов
/ 28 января 2019

TLDR; Как напрямую вызвать установщик родительского класса объекта, не вызывая установщик дочернего объекта вне родительского и дочернего классов?


Я знаю, что если решениесуществует, это может быть очень хакерским / волшебным, но я не против.Вот сценарий:

  • Parent - это класс из сторонней библиотеки, поэтому я вообще не могу изменить этот код.
  • Child - это класс из моей кодовой базы,но я бы хотел оставить магический код вне его, поскольку класс Prop может использоваться с различными классами "Child".
  • Prop - это класс, в котором может находиться магический кодесли необходимо.

Мне нужно получить доступ к установщику Parent x через объект Child без вызова установщика x Child.

Это вообще возможно?

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();

1 Ответ

0 голосов
/ 28 января 2019

Reflect.set здесь для вашего спасения!Это позволяет передавать приемник отдельно:

setX() {
  Reflect.set(Parent.prototype, "x", 0, this.child); // invokes the Parent.protype.x setter
}

Альтернативы могут быть Object.getOwnPropertyDescriptor(Parent.prototype, "x").set.call(this.child, 0) или просто this.child._x = 0 (если вам не нужно запускать установочный код).


Так что, пока это возможно, я бы порекомендовал пересмотреть ваш дизайн.Может быть, наследование - это неправильный подход, и вы должны использовать состав вместо 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;
  }
}
...