在咖啡脚本中扩展多个类

时间:2012-01-30 13:54:18

标签: coffeescript

The documentation解释如何扩展类

class Zebra extends Animal
    ...

但是我如何扩展多个类?以下是工作

class Sidebar extends Controller, EventEmitter
    ...

但我希望如此。这背后的JavaScript能够使用__extend函数扩展任意数量的类,但有没有办法在咖啡脚本中实现?

3 个答案:

答案 0 :(得分:37)

猜猜我会回答我自己的问题。我最终处理这个问题的方法是将我所有的类扩展到我称之为“ SuperClass ”的类中(名称无关紧要)。从那个班级我可以扩展任意数量的课程。无论如何,这个班级看起来像这样

moduleKeywords = ['included', 'extended']

class SuperClass
    @include: (obj) ->
        throw('include(obj) requires obj') unless obj
        for key, value of obj.prototype when key not in moduleKeywords
            @::[key] = value

        included = obj.included
        included.apply(this) if included
        @

几乎只是从Spine偷走了它。从SuperClass扩展的类的一个例子:

class Sidebar extends SuperClass

    # Include some other classes
    @include Controller
    @include EventEmitter

    ###
    Constructor function
    ###
    constructor: ->
        # Call extended constructors
        Controller.call @
        EventEmitter.call @

        console.log 'Sidebar instantiated'

请注意,要调用继承类的构造函数,将使用@ / this作为上下文调用类函数。我还不需要扩展类函数,但我想它与调用父构造函数非常相似:

someFunction: ->
    ExtendedClass::someFunction.call @

如果我错了,请编辑这篇文章。还请原谅我缺乏类继承术语 - 我不是专家


更新:还可以为SuperClass定义一个构造函数,该构造函数在实例化时自动调用所有包含的类的构造函数。这样你只需要从子类中调用super()。虽然

,但我并没有为此烦恼

答案 1 :(得分:6)

这被称为mixin。 CoffeeScript将永远不会包含它们,因为您可以在the CoffeeScript FAQ的“类”部分中阅读。但是in this Gist中存在各种实现,Little Book,JS的this one似乎也适用于CoffeeScript类。

答案 2 :(得分:2)

您可以使用小助手,通过正确的调用super创建正确的原型链。 链中的现有类没有被违反,使用他们的“预测”

https://gist.github.com/darrrk/75d6a6a4d431e7182888

virtual_class = (classes...)->
  classes.reduceRight (Parent, Child)->
    class Child_Projection extends Parent
      constructor: ->
        # Temporary replace Child.__super__ and call original `constructor`
        child_super = Child.__super__
        Child.__super__ = Child_Projection.__super__
        Child.apply @, arguments
        Child.__super__ = child_super

        # If Child.__super__ not exists, manually call parent `constructor`
        unless child_super?
          super

    # Mixin prototype properties, except `constructor`
    for own key  of Child::
      if Child::[key] isnt Child
        Child_Projection::[key] = Child::[key]

    # Mixin static properties, except `__super__`
    for own key  of Child
      if Child[key] isnt Object.getPrototypeOf(Child::)
        Child_Projection[key] = Child[key]

    Child_Projection

示例:

class My extends virtual_class A, B, C