Proper private constructors for ActionScript 3.0

Here’s a useful tip for Flash and Flex programmers. ActionScript 3.0 is great, but has no Singletons.

Samuel Agesilas has a solution that successfully prevents subclasses from calling the constructor using super(), but it doesn’t prevent other code from creating new instances of a class with new

Therefore I present to you a crafty hack to make a constructor truly private: add a required argument to the constructor, which must be set to a secret value that is only known to the class:

class Singleton {
 
    private static var _instance:Singleton = null;
 
    // secret known only to this class
    private static const secret:Number = Math.random();
 
    /**
     * @private
     */
    public function Singleton(enforcer:Number) {
        if (enforcer != secret) {
            throw new Error("Error: use Singleton.instance instead");
        }
    }
 
    /**
     * Global single instance
     */
    public static function get instance():Singleton {
        if (_instance == null) {
            _instance = new Singleton(secret);
        }
        return _instance;
    }
}

This method also has the advantage that it is very fast, and offers a level of compiler protection: new Singleton() will fail at compile time. A user could make the compilation work by passing in, for example new Singleton(42), but there is a very high* chance of that failing at runtime.

Use this technique whenever a constructor should only be called from within a class, to save your users from the all too easy mistake of of creating a second instance of a singleton.

* Geeky aside: the change of guessing the result of Math.random() is 1 to 2^52 against, or 1/4,503,599,627,370,496. This is because 64 bit floating point numbers have a 52 bit mantissa.

Update: Grant Skinner has another way of doing the same thing. His is probably more elegant, but less amusing, and amusingness is a trait I value in language hacks. Also, his solution is not checked at compile time. Andrew Trice had a go too. His version requires an extra argument so provides compile time checking, but can be defeated by calling new Singleton(Singleton.getInstance). Thanks for the links shaun.

Update 2: Ho hum, Eric J Feminella has a solution that is arguably better than mine, since it is properly checked at compile time, i.e. you can’t fool it by passing in any int, and falling back on runtime checking (though null would work). I still contend that my solution is more amusing though :o)

10 thoughts on “Proper private constructors for ActionScript 3.0”

  1. nice one! i’ve seen quite a couple of solutions to this problem, but i like the creativity of yours! surely the enforcer should be a Number though – casting the result of Math.random() to an int will always give you 0, rendering the enforcer useless ;)

  2. The lack of actual Language constructs is a frustrating limitation of ActionScript 3, however, the limitations are helpful in that they force us to dig down a little deeper into the language to find what we can use to develop creative solutions to these limitations. It’s a fun challenge.

    I also wrote a post awhile back which explains a way to create Abstracts in AS3 which you guys might find helpful as well.

    http://www.ericfeminella.com/blog/2007/01/16/pseudo-abstract-classes-in-as3/

  3. True. Old school JavaScript was a great language for hacking language features, from automagical memoization to AOP, if you understood it well enough. This just carries on in the same tradition.

  4. cool trick. Thanks for sharing. I was looking for a way to do the private constructor singleton thing in AS3 like I did AS2 – while not perfect, this will certainly do the trick. :)

  5. class Singleton {
    public function Singletor(lock:Class) {
    if(lock != PrivateConstruct) throw new Error…
    }
    }
    class PrivateConstruct {}

Leave a Reply

Your email address will not be published. Required fields are marked *