用JavaScript合成和混合

时间:2019-05-31 14:11:05

标签: javascript multiple-inheritance

我正在学习Javascript中的合成。因此,我想问一下这是否是正确的处理方式。

我做了一些看起来像这样的练习:

    class Animal {
    // constructor() {
    // }
    eat = () => {
        console.log("this creature is eating");
    }
}

const AnimalsWithWings = superclass => class extends superclass {
    constructor(Feathers, ...args) {
        super(...args);
        Object.assign(this, { Feathers });
    }
}

const CanDive = superclass => class extends superclass {
    // constructor( ...args) {
    //     super(...args);
    // }
    dive = () => {
        console.log("Can Dive");
    }
}

class Duck extends AnimalsWithWings(CanDive(Animal)) {
    constructor(eats, ...args) {
        super(...args);
        Object.assign(this, { eats });
    }
}

const duffy = new Duck("watermelon", true);
console.log(duffy);

duffy.dive();
duffy.eat()

我仍在学习中,所以我只需要一些指示。

1 个答案:

答案 0 :(得分:1)

它或多或少地完成了您的预期?然后,确保这是一种正确的方法,无论“正确”在这里是什么意思。

在我看来,它就像我将其弹出到控制台中时一样。我真的不能在您的代码上多说什么,因为除了将Ducks分解成原子块之外,我不确定它要建模的具体领域。

但是,如果您要这样做,我个人更喜欢使用params对象,而不是像AnimalsWithWings那样更改构造函数签名。这样,额外参数化的顺序并不取决于应用混合的顺序,我认为这是一个惊喜。惊喜很糟糕。

const AnimalsWithWings = superclass => class extends superclass {
    // Everyone receives the same `params` object.
    // They only take what they know about, and ignore the rest.
    constructor(params) {
        super(params);
        Object.assign(this, { Feathers: params.Feathers });
    }
}

就个人观点而言,我将其命名为WithDivingWithWings,只是为了保持某种一致的命名方案,并更好地暗示它们是修饰符,而不是“真实的”基类

您的代码确实使每个Duck都拥有一个原型链,每个原型链有4个较长的原型,但是,无论如何。如果某种原因导致性能出现问题,则可以创建一个实用程序函数来优化混入过程或其他操作。压平原型。

您的代码还允许您在方法中调用super.method(),尽管您是否应该在mixin中使用它一直是有争议的。我会说你不应该,除非你想让你的mixins隐式地相互依赖,这是一个惊喜。

还有很多其他的混合方法。

  • 您可以创建一个实用程序函数,将所有原型压平为一个新的原型,并从扩展的原型返回基类。 (如果要正确处理Object.assign() / get访问器之类的东西,请务必迭代属性描述符,而不仅仅是在进行平坦化时仅使用set)。
  • 您可以避开类,而直接创建原型对象,并使用Object.create()创建实例。 (关于迭代属性描述符的同样操作。)
  • 您可以使用对Object.create()的一堆迭代调用来创建Duck原型,而不是迭代地扩展基类。
  • 您可以使用辅助控制器类来控制其他行为,而不必将行为直接组合到基础中。
  • 您可以只用数据处理普通对象,然后将对象传递给期望该对象具有某些属性以便执行操作的函数。 (有趣的是,被称为“鸭式打字”),我会认为这并不是真正的混合,只是调用函数,但是如果它实际上完成了同样的事情……
  • 目前可能我还无法真正想到的一堆其他东西。所有这些都是在一些基本事物上粘贴行为。