Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class inheritance, and requiring subclasses from different files with Coffeescript

I am trying to organize my code a bit but having issues with undefined superclasses. I'm hoping it's just a load path problem, but I can't figure it out. I am running this with:

coffee rooms.coffee

rooms.coffee

Room = require('./rooms/room')

module.exports = class Rooms extends Object
    constructor: ->
        @

rooms/room.coffee

module.exports = class Room
    @Active: require('./active')

    constructor: (@id) ->
        @users = {}

rooms/active.coffee

Room = require('./room')

console.log Room #=> {}

module.exports = class Active extends Room
    constructor: (@id) ->
        @type = "Active"
        super

And if I try to do new Active, I get the following error:

TypeError: Cannot read property 'constructor' of undefined

Active's super is listed as undefined:

[Function: Active] __super__: undefined

Why Room undefined? (or rather, just an empty Object?)

Update

This was caused by a circular dependency as many people below pointed out. I ended up just putting the subclass definitions right inside of the baseclass definition, rather than try to keep them in separate files. Something like this:

class Room
  constructor: ->
    # ...

  class @Active extends Room
    constructor: ->
      # ...

  class @Inactive extends Room
    constructor: ->
      # ...

active   = new Room.Active
inactive = new Room.Inactive
like image 226
bricker Avatar asked Jun 03 '26 07:06

bricker


1 Answers

This is a case where simplifying the code down to its most primitive parts (while still seeing errors) is illuminating. If we remove the requires and strip out most of the code, we can get a structure like this:

class Room
  @foo = "bar"

class Active extends Room

console.log Room.foo

which prints: bar as expected.

So now lets try getting a little closer to the original example:

class Room
  @foo = Active

class Active extends Room

console.log Room.foo

This prints undefined because Active was not defined when Room.foo was defined.

Finally, let's look at the case were the definitions are reversed:

class Active extends Room

class Room
  @foo = Active

console.log Room.foo

This throws an error because it isn't possible to extend undefined.

The last two cases represent changing the require order in your original example. Having the definition of a base class depend on its subclass should cause your OOP alarm bells to start ringing! :)

There may be a way to change the definitions slightly to make this work, but code with these kinds of mutual dependencies tends to be unmaintainable at best. I'd recommend figuring out a way to completely decouple the classes.

like image 194
David Weldon Avatar answered Jun 05 '26 19:06

David Weldon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!