Расширить класс и передать все аргументы конструктора супер - PullRequest
10 голосов
/ 10 мая 2011

Как бы вы расширили класс с помощью CoffeeScript, но передали бы аргументы конструкции super?

Например:

class List extends Array
    # Some other stuff to make it work...

list = new List(1,2,3)

console.log list
[1, 2, 3]

Ответы [ 4 ]

24 голосов
/ 10 мая 2011

Как правило, это будет работать без дополнительного кода; родительский конструктор используется, если явно не переопределен:

class A
  constructor: ->
    console.log arg for arg in arguments

class B extends A

new B('foo') # output: 'foo'

И проблема не в том, что у Array нет constructor метода:

coffee> Array.constructor
[Function: Function]

Проблема в том, что Array это просто странно . Хотя массивы в принципе являются «просто объектами», на практике они хранятся по-разному. Поэтому, когда вы пытаетесь применить этот конструктор к объекту, который не является массивом (даже если он проходит тест instanceof Array), он не работает.

Итак, вы можете использовать решение Acorn, но тогда вы можете столкнуться с другими проблемами в будущем (особенно если вы передаете List чему-то, что ожидает истинный массив). По этой причине я бы рекомендовал реализовать List в качестве оболочки вокруг экземпляра массива, а не пытаться использовать наследование от нативного типа объекта.

Пока мы обсуждаем эту тему, одно очень важное уточнение : Когда вы используете super само по себе, передает все аргументы! Это поведение позаимствовано у Ruby. Так

class B extends A
  constructor: ->
    super

передаст все аргументы конструктору A, а

class B extends A
  constructor: ->
    super()

вызовет конструктор A с без аргументов.

8 голосов
/ 10 мая 2011
class List extends Array
    constructor: ->
        @push arguments...

    toString: ->
        @join('-')

list = new List(1, 2)

list.push(3)

list.toString()

=>

'1-2-3'
2 голосов
/ 09 октября 2014

Использование extends в CoffeeScript предполагает, что суперкласс будет также в CoffeeScript.Если вы используете класс не-CS, например, Array в исходном вопросе, то вы можете столкнуться с проблемами.

Это решило для меня общий случай.Это немного хак, потому что он использует _super, который, вероятно, не предназначен для использования в скомпилированном JS.

class MyClass extends SomeJsLib

  constructor: ->
    _super.call @, arg1, arg2

Или если вы просто хотите передать аргументы от вызывающей стороны:

class MyClass extends SomeJsLib

  constructor: ->
    _super.apply @, arguments
0 голосов
/ 15 октября 2012

В своем исследовании javascript мне потребовался универсальный способ создания класса с динамическим числом аргументов конструктора.Как уже упоминалось, это не будет работать для массива, насколько я знаю, он будет работать только для классов стилей кофейных сценариев.

Вызов определенной функции с динамическим числом аргументов достаточно прост с помощью .apply

args = [1, 2, 3]
f = measurement.clone

f.apply measurement, args

Класс может расширять класс, сохраненный в переменной.В результате мы можем написать функцию, которая возвращает новые подклассы.

classfactory = (f) ->
    class extension extends f

Собрав все это вместе, мы можем создать функцию, которая возвращает новые подклассы, в которых мы apply аргументируем суперклассКонструктор.

classwitharguments = (f, args) ->
    class extension extends f
        constructor: () ->
            extension.__super__.constructor.apply @, args

Чтобы использовать эту новую фабрику

args = [1, 2, 3]
instance = new (classwitharguments Measurement, args)

Мысли?Комментарии?Предложения?Ограничения, о которых я не думал?Дайте мне знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...