How to call "super" from a callback in coffeescript
class Foo
a: ->
x.call =>
super
will not compile as I can't call super from anonymous class. However my intention is to开发者_C百科 call the superclass method for 'a'. Is this a missing capability in coffeescript?
Note that I change the code to
class Foo
a: ->
x.call =>
return Foo.__super__.a.apply(this, arguments)
to make it work but that just ain't coffeescript right!
Your proposed solution of writing out Foo.__super__.a.apply(this, arguments)
is, I'm afraid, basically as good as you're going to get. CoffeeScript allows you to write things like
a = ->
b = ->
super
(in which case super
points to b
's super function), so it would be a bit confusing to have super
within
a: ->
x =>
super
point to a
's super function. You could raise an issue to ask for this to be allowed, though. It's not ambiguous from a compilation standpoint, just a bit odd-looking.
Here's something you could try to be a little more elegant:
class Foo
constructor: ->
@sup = Foo.__super__
a: ->
x =>
@sup.a.apply this, arguments
I've encountered the same problem and solved it like this:
ChainSuper = (classType, memberName, useFatArrow) ->
original = classType::[memberName]
superf = classType.__super__.constructor.prototype[memberName]
callSuper = (thisRef, args, superArgs) ->
for i in [0...superArgs.length]
args[i] = superArgs[i]
superf.apply thisRef, args
classType::[memberName] = if useFatArrow
(args...) ->
original.call @, args..., (superArgs...) =>
callSuper @, args, superArgs
else
(args...) ->
original.call @, args..., (thisRef, superArgs...) ->
callSuper thisRef, args, superArgs
This is very non-kosher and will probably break if the Coffeescript compiler's class semantics change. While waiting for that, however, I'm able to say:
CheckSuper = (ref, message) ->
if ref instanceof Superclass
alert "Works with #{message}"
class Superclass
plus: (values...) ->
CheckSuper @, 'plus'
@val = 0
for i in values
@val += i
alert @val
minusBase: 0
minus: (values...) ->
CheckSuper @, 'minus'
@val = @minusBase
for i in values
@val -= i
alert @val
class Subclass extends Superclass
plus: (values..., Super) ->
setTimeout (=> Super @), 0
ChainSuper @, 'plus'
minus: (values..., Super) =>
@minusBase = values[0]
setTimeout (-> Super values[1...]..., 0), 0
ChainSuper @, 'minus', true
subInstance = new Subclass()
subInstance.plus 1, 2, 3, 4
minus = subInstance.minus
minus 100, 10, 1
Please notice, that with this solution, if you pass n arguments to a Super() when the method has been called with more than n arguments, only the first n arguments get overwritten in the call to the super method and the rest will be passed on unchanged.
Now you can use super::method() instead.
精彩评论