【问题标题】:what is an elegant mixin/composition syntax for ES6 classes?什么是 ES6 类的优雅混合/组合语法?
【发布时间】:2019-09-28 16:35:09
【问题描述】:

我正在寻找一种干净简单的方法来将方法混合到不同的类中。我能找到的大多数示例都使用 JS prototype,例如 this

示例代码:

const _ = require("underscore")

let actions = {
  speak() {
    console.log(this.name + " animal speak")
  },

  look() {
    console.log(this.name + " animal looks")
  }
}

class Dog {
  constructor(name) {
    console.log("new Dog", name)
    this.name = name

    // modify instance and return
    let that = _.extend(this, actions)
    return that
  }

  speak() {
    console.log(this.name + " dog speaks")
  }

  bark() {
    console.log(this.name + " dog barks")
  }

}

function test() {
  let rover = new Dog("rover")

  // speak in "actions" overrides Dog.speak method
  rover.speak() // => rover animal speak

  // runtime works but ts-lint doesn't like it
  // look property doesn't exist on type 'dog'
  rover.look() // => rover animal looks

  // from dog since the method doesn't exist on actions
  rover.bark() // => rover dog barks
}

test()

所以要使用原型,我可以将上面的内容修改为:

Object.assign(Dog.prototype, actions)

然后只使用返回this的普通构造函数

class Dog {

  constructor(name) {
    this.name = name
  }
...
}

Object.assign(Dog.prototype, actions)

在这两种情况下,mixin speak 方法将替换 Dog Class speak 方法,好的。

所以我的问题是:是否有任何其他更简单/更清洁的方法可以跨类混合方法?

在添加到原型方面,上述内容有什么问题吗?那是创建实际方法的副本吗?如果它只存在于原型中而不是每个实例中,我想它是可以的,但并不完全清楚那里的任何内存影响。

【问题讨论】:

  • @RobertHarvey 谢谢,其实很相似。提出了从主类调用混合方法的好处,就像我拥有的​​那样。
  • 我的方法基本有效,包括getter/setter。在处理这种技术可能导致问题的类/实例时,还有哪些其他极端情况?
  • 上面的一个问题是TSLint不知道混入的方法,所以我得到很多TS lint错误,无法跳转到实现等。
  • 备忘录 - 更多示例 alligator.io/js/class-composition

标签: javascript mixins prototypal-inheritance


【解决方案1】:

作为使用 mixins 的替代方法,您可以使用 extends 的继承来覆盖类上的方法。

与 mixins 相比,继承的缺点是一次只能扩展一个类,但可以使用多个 mixin。所以这取决于你的用例是什么。

这是一个例子:

class Animal {
  constructor(name) {
    console.log("new", this.constructor.name, name)
    this.name = name

  }
  
  speak() {
    console.log(this.name + " animal speak")
  }

  look() {
    console.log(this.name + " animal looks")
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name)
  }

  speak() {
    console.log(this.name + " dog speaks")
  }

  bark() {
    console.log(this.name + " dog barks")
  }

}

const dog = new Dog('Fred')
// Will call the overridden speak method on Dog
dog.speak() // Fred dog speaks
// Will call look on Animal as it hasn't been overriden in Dog
dog.look() // Fred animal looks

【讨论】:

  • mixins 不应该是继承的替代吗?来自this page“mixin 是一个包含供其他类使用的方法的类,而不必成为其他类的父类.... Mixin 有时被描述为“包含”而不是“继承” "。
  • 是的,但我认为 mixin 的主要优点是绕过多重继承。也许这就是@dcsan 正在尝试做的事情,但在他们的示例中,使用类继承似乎可行。
  • mixins一般用于“多重继承”,只能使用extends关键字继承单个原型。
  • 我提出这个答案是为了根据要求提出一个潜在的“更简单/更清洁”的解决方案,但如果需要多重继承,它可能不符合要求
  • 无论如何,您似乎没有回答所提出的问题。 OP 要求 mixins,但您提供普通继承。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-04
  • 1970-01-01
  • 1970-01-01
  • 2021-09-29
相关资源
最近更新 更多