【问题标题】:Extending multiple classes in coffee-script在咖啡脚本中扩展多个类
【发布时间】:2012-02-22 07:26:16
【问题描述】:

The documentation解释如何扩展一个类

class Zebra extends Animal
    ...

但是如何扩展多个类?以下操作不起作用

class Sidebar extends Controller, EventEmitter
    ...

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

【问题讨论】:

  • 你可以看看这个讨论:github.com/jashkenas/coffee-script/issues/452
  • suds... 这对我来说不是个好兆头
  • JavaScript 使用原型继承...在幕后,extends 使用单个属性“原型”来创建链...只有当对象是原型时,您才能从多个对象“继承”链...例如Zebra 可以扩展 VegetarianAnimal,vegetarianAnimal 可以扩展 Animal。

标签: coffeescript


【解决方案1】:

我想我会回答我自己的问题。我最终处理这个问题的方式是从一个我称之为“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()。不过我并没有为此烦恼

【讨论】:

  • 我认为调用 super() 是行不通的。您需要某种数组来存储 @included 对象的类。这不起作用,因为您需要将此相同的变量重置为 []
【解决方案2】:

这称为mixin。 CoffeeScript 永远不会在本地包含它们,您可以在 the CoffeeScript FAQ 的类部分中阅读。但是有各种实现,in this GistLittle Book 和 JS 的 this one 似乎也适用于 CoffeeScript 类。

【讨论】:

    【解决方案3】:

    您可以使用 little helper,它通过正确的调用 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
    

    【讨论】:

      猜你喜欢
      • 2013-10-30
      • 1970-01-01
      • 2014-04-10
      • 1970-01-01
      • 2013-01-09
      • 2012-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多