2012-01-30 163 views
16

The documentation解釋如何擴展類擴展多個類的咖啡腳本

class Zebra extends Animal 
    ... 

但我怎麼擴展多個類?下面確實沒有工作

class Sidebar extends Controller, EventEmitter 
    ... 

但我希望它做到了。這背後的JavaScript不僅可以使用__extend函數擴展任意數量的類,但有沒有辦法在coffee-script中執行它?

+0

你可以看看這個討論:https://github.com/ jashkenas/coffee-script/issues/452 – qiao 2012-01-30 13:57:57

+0

suds ...這對我來說不是一個好兆頭 – Hubro 2012-01-30 14:02:18

+0

JavaScript使用原型繼承...在幕後,extends使用單個屬性'原型'來創建鏈...您可以有「繼承」f只有在對象是原型鏈時才從多個對象中提取...斑馬可以延伸素食動物和素食動物延伸動物。 – Jaider 2012-07-23 22:14:25

回答

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。從超類延伸的類的例子:

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 @ 

,如果我錯了,請編輯這個職位。也請原諒我沒有繼承類的術語 - 我不是專家


更新:你也可以定義超類構造函數自動要求對所有實例包含類的構造函數。這樣你只需要從子類中調用super()即可。我還沒有打擾,雖然

+0

我想調用超級()將無法正常工作。您需要某種存儲'@ include'd對象的類的數組。這不起作用,因爲你需要重置這個相同的變量到'[]'。 – Atmocreations 2015-02-17 11:15:28

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