【问题标题】:Calling methods implemend by mixins without super调用方法由没有 super 的 mixins 实现
【发布时间】:2019-09-04 08:19:44
【问题描述】:

我想要一个 mixin 类,它期望具体类定义一个特定的方法。比如:

function BaseMixin(Base) {
  class Mixin extends Base {
    doSomething() {
      this.onSomethingDone()
    }
  }

  return Mixin
}

同时,我允许可选的 mixins,它们也可能声明这样的方法。最终结果是具体类和每个 mixin 都需要调用 super.onSomethingDone 并且因为应用 mixin 的顺序可以改变,他们还必须检查该方法是否存在:

function SecondaryMixin(Base) {
  class Mixin extends Base {
    onSomethingDone() {
      if (super.onSomethingDone)
        super.onSomethingDone()

      // stuff specific to SecondaryMixin
    }
  }

  return Mixin
}

class ConcreteClass extends SecondaryMixin(BaseMixin(HTMLElement)) {
  doSomething() {
    if (super.onSomethingDone)
      super.onSomethingDone()

    // stuff specific to ConcreteClass
  }
}

这是乏味且容易出错的。相反,是否可以只让实现者执行他们的specific stuff 并在BaseMixin 中以某种方式迭代并从所有应用的mixins 中调用onSomethingDone 的所有实现?

function BaseMixin(Base) {
  class Mixin extends Base {
    doSomething() {
      for (let onSomethingDone of getAllImplementationsThereof()) {
        onSomethingDone()
      }
    }
  }
}

【问题讨论】:

  • 只是 FWIW,那些通常不会被称为 mixins。这些是可选应用的超类。 Mixin 不参与继承。

标签: javascript inheritance mixins


【解决方案1】:

你可以像这样实现getAllImplementations

function getAllImplementationsOf(cls, methodName) {
    let fns = [];

    cls = Object.getPrototypeOf(cls);

    while (cls) {
        if (cls.prototype && cls.prototype.hasOwnProperty(methodName))
            fns.push(cls.prototype[methodName]);
        cls = Object.getPrototypeOf(cls);
    }

    return fns;
}

//


function FirstMixin(Base) {
    return class Mixin extends Base {
        work() {
            console.log('first')
        }
    }
}

function SecondMixin(Base) {
    return class Mixin extends Base {
        work() {
            console.log('second')
        }
    }
}

class Base {
}

class ConcreteClass extends FirstMixin(SecondMixin(Base)) {

    work() {
        for (let fn of getAllImplementationsOf(this.constructor, 'work'))
            fn.call(this);
        console.log('done!')
    }
}

new ConcreteClass().work();

话虽如此,我不确定extends 是否是实现mixin 的正确工具,正是因为这类问题。我宁愿研究代理。

【讨论】:

  • 我更喜欢您的原始实现。但两者都有效。
猜你喜欢
  • 1970-01-01
  • 2022-07-15
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 1970-01-01
  • 2018-03-17
相关资源
最近更新 更多