Singleton pattern in Chuck

24.04.14

Whole-Play consists of many objects interacting amongst themselves, so I needed a way to share data between them all (like tempo, time signature, etc). One (the?) way to do this in Chuck is with static members, and it seemed like a good scenario for a singleton class. Here's how I've implemented this in Chuck:

public class SingletonDemo {
    
    // Singleton object reference
    static SingletonDemo @ _instance;

    // Needed to make sure you don't create instances before calling instance() once
    static int _instanceAccessedProperly;

    // Instance vars
    int i;
    
    // "Private constructor"
    // This is not really a constructor at all, just stops you from creating instances of this class
    if (_instance != null  || !_instanceAccessedProperly) {
        <<< "[ERROR] Cannot create instances of SingletonDemo, use SingletonDemo.instance() instead" >>>;
        me.exit();
    }
    
    // Static method to retrieve the singleton instance
    fun static SingletonDemo instance() {
        if (_instance == null) {
            true => _instanceAccessedProperly;
            new SingletonDemo @=> _instance;
        }
        return _instance;
    }
    
    // Static method to modify the singleton instance, without the need to retrieve it first
    fun static void init(int i) {
        i => instance().i;
    }
    
}

Now all the shared data I need is encapsulated in one class, which of course can also include methods. The instance is created on first call to SingletonDemo.instance():

SingletonDemo.instance() @=> SingletonDemo singleton;

The tricky bit is the "private constructor", which is simulated in the initialization block. I need an extra static bool to check that you've called instance() at least once, otherwise you could create a instance to begin with. This block is run every time an instance is attempted, and thus it makes sure that you can't type:

// This will fail and exit:
SingletonDemo invalidInstance;

Note that you can create a reference and then call instance():

// This will work fine:
SingletonDemo @ validInstance;
SingletonDemo.instance() @=> validInstance;

The static init() method is just a convenience method, that allows you to interact with the instance without the need to retrieve it first with instance().

// Modify the instace without retrieving it first
SingletonDemo.init(5);

I'm attaching a zip with a test case in case anybody wants to explore this.

Download

0 comments

Add a comment


[ change image ]

PS: no links allowed in comment.


End of page. Back to page navigation.