How to create coffeescript singleton subclass

I've created a singleton class which I want to extend. It (half) works in that it only creates a single instance of the class, but properties added to the subclass are undefined. Here is the original singleton:

class Singleton
   _instance = undefined
   @getInstance: ->
      if _instance is undefined
         console.log 'no instance exists, so create one'
         _instance = new _Singleton()
      else
         console.log 'an instance already exists.'

class _Singleton
   constructor: ->
      console.log 'new singelton'

module.exports = Singleton

And here is the subclass:

Singleton = require('./singleton')

class Stinky extends Singleton
      constructor: ->
         var1 : 'var1'


module.exports = Stinky

Now if I use the following in my node app:

Stinky = require './stinky'
thing1 = Stinky.getInstance()
thing2 = Stinky.getInstance()
console.log "Thing var1: #{thing1.var1}"

the getInstance() method behaves as expected, but var1 is undefined. If I do this same thing on non singleton classes they work fine. Thanks.

I trimmed your code down a bit. Here are the 2 remaining classes:

class Singleton
  @_instance: null
  @getInstance: ->
    @_instance or= new @( arguments... )

class Stinky extends Singleton
  constructor: ( @num ) ->

thing1 = Stinky.getInstance( 1 )
thing2 = Stinky.getInstance( 2 )

console.log( thing1.num, thing2.num )

I made the following changes:

  • Merged Singleton and _Singleton
  • Changed _instance to @_instance so that it would be attached to Singleton rather than its prototype
  • Added arguments splat in getInstance (in case arguments are needed)
  • Pointing getInstance() to extended object rather than Singleton

In this example, I used 2 different numbers to ensure that the 2nd constructor was never called.

I see how you're using the _Singleton class to try to simulate a private class, but unfortunately I don't think you can use it in this case.

Here is some code that works:

class Singleton
   _instance = undefined

   constructor: ->
      console.log 'new singleton'

   @getInstance: ->
      if _instance is undefined
         console.log 'no instance exists, so create one'
         _instance = new @()
      else
         console.log 'an instance already exists.'
      _instance

class Stinky extends Singleton
      constructor: ->
         console.log 'Stinky constructor'
         @var1 = 'var1'


thing1 = Stinky.getInstance()
thing2 = Stinky.getInstance()

console.log "Thing var1: #{thing1.var1}"​​​​​​​​​​​​​​​​​​, thing1, thing2​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

I removed the Node.js (require) code, but adding that in should be straightforward. The main difference is that the instance my code is creating is an instance of @ or this. Doing so will make sure your constructor is called first then continue up the parent chain. Your code was explicitly creating an instance of _Singleton so your Stinky constructor was never being called. Another minor issue that you would have eventually noticed was that your getInstance method was not actually returning a instance of _instance.

I hope this helps,

Sandro

I'm not sure what the goal is, but you can achieve the same result by making Singleton a real singleton (a plain object):

Singleton =
    doNothing: ->
        # ...
    doMoreNothing: ->
        # ...

class Stinky
    constructor: ->
        @var1: 'var1'
    getInstance: ->
        return Singleton

It doesn't make much sense for Singleton to have a method that returns itself.