Расширение нескольких классов в кофе-скрипте - PullRequest
16 голосов
/ 30 января 2012

Документация объясняет, как расширить класс

class Zebra extends Animal
    ...

Но как мне расширить несколько классов? Следующее не работает

class Sidebar extends Controller, EventEmitter
    ...

Но я бы этого хотел. JavaScript, стоящий за этим, более чем способен расширять любое количество классов с помощью функции __extend, но есть ли способ сделать это в coffee-script?

Ответы [ 3 ]

37 голосов
/ 30 января 2012

Думаю, я просто отвечу на свой вопрос.То, как я в итоге справился с этим, расширяет все мои классы из класса, который я называю " 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
        @

В значительной степени просто украл его у Позвоночник .Пример класса, расширенного из 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() из подкласса.Я не беспокоился об этом, хотя

6 голосов
/ 01 февраля 2012

Это называется mixin .CoffeeScript никогда не будет включать их изначально, как вы можете прочитать в разделе «Классы» FAQ по CoffeeScript .Но есть различные реализации: в этой Gist , в Little Book , и эта для JS, похоже, также работает с классами CoffeeScript.*

2 голосов
/ 16 августа 2014

Вы можете использовать маленький помощник, который создает правильную цепочку прототипов с правильным вызовом 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...