ES6等。是否可以定义一个包罗万象的方法?

时间:2019-04-15 14:46:22

标签: inheritance methods ecmascript-6 object-composition

当要从子级到父级的方法调用级联时,组合是继承的一种有用替代方法,请参见child extended class method calls its super version but that still only sees child data

但是,为了让孩子展示与父类型兼容的接口,必须实现大量可能具有相同格式的存根方法,即它们只是将调用中继到前一个父对象(现在是一个组件)。

我的问题在这里,有可能编写一个包罗万象的方法吗?当没有其他方法被调用时,将调用全部捕获方法。然后,全部捕获只是将调用中继到父组件。因此,存根仅需写入一次。变体可以用于对多个继承进行排序等。

类似这样的东西:

  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 :(得分:0)

使用Fred Truter的函数从类Iterate through methods and properties of an ES6 class中提取方法:

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"

答案 1 :(得分:0)

这是基于isepa的建议,即使用Fred Truter的函数列出方法。这是一个很好的概念,但并不能使我们达到目标。它需要进行测试,以免破坏现有的方法。同样,仅复制方法也是有问题的,因为父级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()