Расширение нескольких классов в кофе script - программирование
Подтвердить что ты не робот

Расширение нескольких классов в кофе script

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

class Zebra extends Animal
    ...

Но как мне расширить несколько классов? Ниже приведена не работа

class Sidebar extends Controller, EventEmitter
    ...

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

4b9b3361

Ответ 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() из подкласса. Я не беспокоился об этом, хотя

Ответ 2

Это называется mixin. CoffeeScript никогда не будет включать их изначально, как вы можете прочитать в разделе "Классы" на "Часто задаваемые вопросы по CoffeeScript" . Но существуют различные реализации, в этом Gist, в Маленькой книге и этот для JS, похоже, также работает с классами CoffeeScript.

Ответ 3

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