10

你将如何使用 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

4 回答 4

24

一般来说,这不需要额外的代码就可以工作;除非明确重写,否则使用父构造函数:

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 的解决方案,但随后您可能会遇到其他问题(特别是如果您将 a 传递List给需要真正数组的东西)。出于这个原因,我建议将其实现List为数组实例的包装器,而不是尝试使用从本机对象类型继承。

当我们谈到这个主题时,一个非常重要的澄清:当你单独使用时super,它确实传递了所有参数!这种行为是从 Ruby 借来的。所以

class B extends A
  constructor: ->
    super

会将所有参数传递给A的构造函数,而

class B extends A
  constructor: ->
    super()

将调用A带参数的构造函数。

于 2011-05-10T19:37:00.947 回答
8
class List extends Array
    constructor: ->
        @push arguments...

    toString: ->
        @join('-')

list = new List(1, 2)

list.push(3)

list.toString()

=>

'1-2-3'
于 2011-05-10T17:47:49.130 回答
2

在 CoffeeScript 中使用extends期望超类也在 CoffeeScript 中。如果您使用的是非 CS 课程,例如Array在原始问题中,那么您可能会遇到问题。

这解决了我的一般情况。这有点像 hack,因为它使用_super了可能不打算在编译的 JS 中使用的东西。

class MyClass extends SomeJsLib

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

或者,如果您只想从调用者传递参数:

class MyClass extends SomeJsLib

  constructor: ->
    _super.apply @, arguments
于 2014-10-08T20:26:25.803 回答
-1

在我对 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)

想法?评论?建议?我没有想到的限制?让我知道。

于 2012-10-15T17:52:14.937 回答