Fresheyeball
Fresheyeball

Reputation: 30015

Coffeescript static inheritance of child classes

This works :

class Foo 
  class @_Bar 
    @narf = ''
    @point : ->
      @narf = 'what'

  class @_Baz extends @_Bar 
    @point : ->
      @narf = 'woo'
      super()

This does not

class Foo 
  class @_Bar 
    @narf = ''
    @point = ->
      @narf = 'what'

  class @_Baz extends @_Bar 
    @point = ->
      @narf = 'woo'
      super()

running Foo._Baz.point() will throw and error.


Please someone explain what is going on here.

Upvotes: 2

Views: 227

Answers (3)

hpaulj
hpaulj

Reputation: 231385

There are a couple of fixes now on github. https://github.com/jashkenas/coffee-script/issues/3232

Currently the node tree for a @foo= method is different from that of a @foo: method. Because of that, a node created with = is never passed to the Class addParameters method, and is never flagged as static.

One solution, which will probably be accepted, makes sure both forms produce the same node tree.

The one I contributed https://github.com/jashkenas/coffee-script/issues/3232#issuecomment-28316501 adds a method to nodes.coffee class Class. This method is a stripped down version of addParameters, and specifically checks a = node tree.

If you need a fix in your own Coffee compiler, modify your src/coffee-script/nodes.coffee file, compile it, and put the resulting node.js in the lib directory (or use the cake build).

Upvotes: 1

hpaulj
hpaulj

Reputation: 231385

This works:

class Foo 
  class @_Bar 
    @narf = ''
    point : ->
      @narf = 'what'

  class @_Baz extends @_Bar 
    @point = ->
      @narf = 'woo'
      super()

alert Foo._Baz.point()  # 'what'
alert new Foo._Bar().point() # 'what'

That is, the compiled @point= super ends up pointing to the instance point:. Its JS is: _Baz.__super__.point.call(this), which is _Bar.prototype.point.call(this). (extends defines: child.__super__ = parent.prototype).

It's clear from past Coffeescript changes that @point: is the intended syntax for static (class) methods (and used that way in the compiler itself).

Upvotes: 2

Trevor Burnham
Trevor Burnham

Reputation: 77416

It seems like a bug in the compiler to me. Writing

class X
  @classMethod: ->

and

class X
  @classMethod = ->

should be equivalent, yet super compiles differently across the two methods. In the first, it compiles correctly:

X.__super__.constructor.classMethod.apply(this, arguments);

In the second, it compiles as if classMethod were an instance method:

X.__super__.classMethod.apply(this, arguments);

Upvotes: 3

Related Questions