扩展类并将所有构造函数参数传递给super

时间:2022-05-20 16:02:32

How would you extend a class using CoffeeScript, but have the construction arguments passed to super?

你如何使用CoffeeScript扩展一个类,但是将构造参数传递给super?

Eg:

例如:

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

list = new List(1,2,3)

console.log list
[1, 2, 3]

4 个解决方案

#1


8  

class List extends Array
    constructor: ->
        @push arguments...

    toString: ->
        @join('-')

list = new List(1, 2)

list.push(3)

list.toString()

=>

=>

'1-2-3'

#2


24  

In general, this would work without additional code; the parent constructor is used unless expressly overridden:

通常,这可以在没有附加代码的情况下工作;除非明确覆盖,否则使用父构造函数:

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

class B extends A

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

And the problem isn't that Array doesn't have a constructor method:

问题不在于Array没有构造函数方法:

coffee> Array.constructor
[Function: Function]

The problem is just that Array is just plain weird. While arrays are "just objects" in principle, in practice they're stored differently. So when you try to apply that constructor to an object that isn't an array (even if it passes the instanceof Array test), it doesn't work.

问题只是Array很奇怪。虽然数组原则上只是“对象”,但实际上它们的存储方式不同。因此,当您尝试将该构造函数应用于不是数组的对象时(即使它通过了instanceof Array测试),它也不起作用。

So, you can use Acorn's solution, but then you may run into other problems down the road (especially if you pass a List to something that expects a true array). For that reason, I'd recommend implementing List as a wrapper around an array instance, rather than trying to use inheritance from a native object type.

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

While we're on the subject, one very important clarification: When you use super by itself, that does pass all arguments! This behavior is borrowed from Ruby. So

当我们讨论这个主题时,一个非常重要的澄清:当你自己使用超级时,它确实通过了所有论点!这种行为来自Ruby。所以

class B extends A
  constructor: ->
    super

will pass along all arguments to A's constructor, while

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

class B extends A
  constructor: ->
    super()

will invoke A's constructor with no arguments.

将调用没有参数的A的构造函数。

#3


2  

Using extends in CoffeeScript expects the superclass to be in CoffeeScript too. If you're using a non-CS class, e.g. Array in the original question, then you may encounter problems.

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

This solved the general case for me. It's a bit of a hack because it uses _super which probably isn't intended to be used in the compiled JS.

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

class MyClass extends SomeJsLib

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

Or if you just want to pass thru arguments from the caller:

或者,如果您只想传递来自调用者的参数:

class MyClass extends SomeJsLib

  constructor: ->
    _super.apply @, arguments

#4


-1  

In my exploration of javascript I required a generic way to create a class with a dynamic number of constructor arguments. As mentioned this won't work for array as far as I know, it will only work for coffee-script style classes.

在我对javascript的探索中,我需要一种通用的方法来创建一个具有动态数量的构造函数参数的类。如上所述,据我所知,这对数组不起作用,它只适用于咖啡脚本样式类。

Calling a specific function with a dynamic number of arguments is easy enough through .apply

通过.apply可以很容易地使用动态数量的参数调用特定函数

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

f.apply measurement, args

A class can extend a class saved in a variable. As a result we can write a function that returns new sub-classes.

类可以扩展保存在变量中的类。因此,我们可以编写一个返回新子类的函数。

classfactory = (f) ->
    class extension extends f

Putting it all together we can create a function that returns new sub-classes in which we apply arguments to the super class's constructor.

将它们放在一起我们可以创建一个函数来返回新的子类,在这些子类中我们将参数应用于超类的构造函数。

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

To use this new factory

要使用这个新工厂

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

Thoughts? Comments? Suggestions? Limitations I didn't think about? Let me know.

思考?注释?建议?限制我没想过?让我知道。

#1


8  

class List extends Array
    constructor: ->
        @push arguments...

    toString: ->
        @join('-')

list = new List(1, 2)

list.push(3)

list.toString()

=>

=>

'1-2-3'

#2


24  

In general, this would work without additional code; the parent constructor is used unless expressly overridden:

通常,这可以在没有附加代码的情况下工作;除非明确覆盖,否则使用父构造函数:

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

class B extends A

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

And the problem isn't that Array doesn't have a constructor method:

问题不在于Array没有构造函数方法:

coffee> Array.constructor
[Function: Function]

The problem is just that Array is just plain weird. While arrays are "just objects" in principle, in practice they're stored differently. So when you try to apply that constructor to an object that isn't an array (even if it passes the instanceof Array test), it doesn't work.

问题只是Array很奇怪。虽然数组原则上只是“对象”,但实际上它们的存储方式不同。因此,当您尝试将该构造函数应用于不是数组的对象时(即使它通过了instanceof Array测试),它也不起作用。

So, you can use Acorn's solution, but then you may run into other problems down the road (especially if you pass a List to something that expects a true array). For that reason, I'd recommend implementing List as a wrapper around an array instance, rather than trying to use inheritance from a native object type.

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

While we're on the subject, one very important clarification: When you use super by itself, that does pass all arguments! This behavior is borrowed from Ruby. So

当我们讨论这个主题时,一个非常重要的澄清:当你自己使用超级时,它确实通过了所有论点!这种行为来自Ruby。所以

class B extends A
  constructor: ->
    super

will pass along all arguments to A's constructor, while

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

class B extends A
  constructor: ->
    super()

will invoke A's constructor with no arguments.

将调用没有参数的A的构造函数。

#3


2  

Using extends in CoffeeScript expects the superclass to be in CoffeeScript too. If you're using a non-CS class, e.g. Array in the original question, then you may encounter problems.

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

This solved the general case for me. It's a bit of a hack because it uses _super which probably isn't intended to be used in the compiled JS.

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

class MyClass extends SomeJsLib

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

Or if you just want to pass thru arguments from the caller:

或者,如果您只想传递来自调用者的参数:

class MyClass extends SomeJsLib

  constructor: ->
    _super.apply @, arguments

#4


-1  

In my exploration of javascript I required a generic way to create a class with a dynamic number of constructor arguments. As mentioned this won't work for array as far as I know, it will only work for coffee-script style classes.

在我对javascript的探索中,我需要一种通用的方法来创建一个具有动态数量的构造函数参数的类。如上所述,据我所知,这对数组不起作用,它只适用于咖啡脚本样式类。

Calling a specific function with a dynamic number of arguments is easy enough through .apply

通过.apply可以很容易地使用动态数量的参数调用特定函数

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

f.apply measurement, args

A class can extend a class saved in a variable. As a result we can write a function that returns new sub-classes.

类可以扩展保存在变量中的类。因此,我们可以编写一个返回新子类的函数。

classfactory = (f) ->
    class extension extends f

Putting it all together we can create a function that returns new sub-classes in which we apply arguments to the super class's constructor.

将它们放在一起我们可以创建一个函数来返回新的子类,在这些子类中我们将参数应用于超类的构造函数。

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

To use this new factory

要使用这个新工厂

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

Thoughts? Comments? Suggestions? Limitations I didn't think about? Let me know.

思考?注释?建议?限制我没想过?让我知道。