ES6 и соавт. Можно ли определить метод всеобщего охвата? - PullRequest
0 голосов
/ 15 апреля 2019

Композиция является полезной альтернативой наследованию, когда кто-то хочет каскадно вызывать методы от дочернего к родительскому, см. метод расширенного класса дочернего элемента вызывает свою супер версию, но он все еще видит только дочерние данные

Однако, чтобы дочерний элемент представлял интерфейс, совместимый с родительским типом, необходимо реализовать потенциально большое количество методов-заглушек, которые имеют одинаковую форму, а именно они просто передают вызов предыдущему родительскому элементу (который сейчас компонент).

Мой вопрос здесь, возможно ли написать метод всеобъемлющего анализа? Метод catch-all вызывается, когда не вызывается ни один из других методов. Тогда всеохватывающее устройство будет просто передавать вызовы родительскому компоненту. Таким образом, заглушка должна быть написана только один раз. Вариации могут быть использованы для сортировки множественного наследования и т. Д.

Примерно так:

  class A {
      constructor(){
        this.x = "super x!";
      }
      f(){
        console.log("I am a super f()!");
      }
      logx(){
        this.f();
        console.log(this.x);
      }
    }

    class B {
      constructor(){
        this.a = new A();
        this.x = "derived x.";
      }
      f(){
        console.log("I am a derived f()");
      }
      logx(){
        this.a.logx();
      }
    }

    let b = new B;
    b.logx();
  I am a super f()!
    super x!

Гипотетически вместо этого будет что-то вроде этого:

 class A {
      constructor(){
        this.x = "super x!";
      }
      f(){
        console.log("I am a super f()!");
      }
      logx(){
        this.f();
        console.log(this.x);
      }
    }

    class B {
      constructor(){
        this.a = new A();
        this.x = "derived x.";
      }
      f(){
        console.log("I am a derived f()");
      }
      catch_all(method_name, ...args){
        this.a.method_name(...args);
      }
    }

    let b = new B;
    b.logx();
  I am a super f()!
    super x!

Ответы [ 2 ]

0 голосов
/ 15 апреля 2019

Это основано на предложении isepa использовать функцию Фреда Трутера для перечисления методов.Это хорошая идея, но она не совсем нас туда привела.Требуется проверка, чтобы не загромождать существующие методы.Также просто копировать методы проблематично, потому что родительский this.variables не будет там или будет псевдонимом дочернего элемента - обратите внимание, что это состав, поэтому они не были предназначены для наследования.Вместо копирования это превращает его в вызов.

    //Fred Truter's function:
    Object.methods = function (klass) {
      const properties = Object.getOwnPropertyNames(klass.prototype)
      properties.push(...Object.getOwnPropertySymbols(klass.prototype))
      return properties.filter(name => {
        const descriptor = Object.getOwnPropertyDescriptor(klass.prototype, name)
        if (!descriptor) return false
        return 'function' == typeof descriptor.value && name != 'constructor'
      })
    }

   Object.compose = function (obj0, obj1, ...constructor_args) {
    obj0[obj1.name] = new obj1(...constructor_args);
    Object.methods(obj1).forEach(
      method => {
        if(!obj0[method]) obj0[method] = (...args) => obj0[obj1.name][method](...args);
      }
    );
  }


    // shows using the composition operator:
    class A {
      constructor(){
        this.x = "super x!";
      }
      f(){
        console.log("I am a super f()!");
        console.log(this.x);
      }
      logx(){
        console.log(this.x);
        this.f();
      }
    }

    class B {
      constructor(){
        Object.compose(this, A);
        this.x = "derived x.";
      }
      // f(){ console.log("I am a derived f()"); }
      logx(){
        console.log(this.x);
        this.f();
      }
    }

    let b = new B;
    b.logx();
    b.f();

И вывод, как и ожидалось:

derived x.
I am a super f()!
super x!
I am a super f()!
super x!

Затем, удалив комментарий из дочерней версии f, мы получим, как и ожидалось:

derived x.
I am a derived f()
0 голосов
/ 15 апреля 2019

Использование функции Фреда Трутера для извлечения методов из класса Перебор методов и свойств класса ES6 :

Object.methods = function (klass) {
    const properties = Object.getOwnPropertyNames(klass.prototype)
    properties.push(...Object.getOwnPropertySymbols(klass.prototype))
    return properties.filter(name => {
        const descriptor = Object.getOwnPropertyDescriptor(klass.prototype, name)
        if (!descriptor) return false
        return 'function' == typeof descriptor.value && name != 'constructor'
    })
}

class A {
    constructor() {
        this.x = "super x!";
    }
    f() {
        console.log("I am a super f()!");
    }
    logx() {
        console.log(this.x + "log");
    }
}

class B {
    constructor() {
        this.a = new A();
        this.x = "derived x. ";
        Object.methods(A).forEach(method => this[method] = this.a[method]);
    }
    logx() {
        console.log(this.x + "log")
    }
}

let b = new B;
b.f(); //"I am a super f()!"
b.logx(); //"derived x. log"
...