Enums and ActionScript's Static Initializers

I discovered today, while trying to synthesize an Enum type, that AS3 has the concept of a static initializer, which is awesome. In a nutshell, a static initializer is kind of like a constructor, but it's for the class object itself, not instances of the class. It gets invoked during classloading, after all static properties have been set, but the class is turned loose for general consumption. Here's an example of an Enum type (named ColorEnum) that uses the static initializer (in bold):

package com.barneyb.test {

  public class ColorEnum {

    public static const BLACK:ColorEnum = new ColorEnum(0x000000);
    public static const WHITE:ColorEnum = new ColorEnum(0xFFFFFF);

    private static var locked:Boolean = false;

    {
      locked = true;
    }

    private var _color:uint;
    public function get color():uint {
      return _color;
    }

    public function ColorEnum(color:uint) {
      if (locked) {
        throw new Error("You can't instantiate ColorEnum");
      }
      _color = color;
    }
  }
}

What this provides is a ColorEnum class that cannot be instantiated, with two instances stored in the BLACK and WHITE static constants. This sort of class locking is equally useful for singletons (think ServiceLocator if you use Cairngorm, though they implement it differently). Usually, you use a private constructor for this type of behaviour, but since AS3 doesn't support that, you have to synthesize it. However, that's not all a static initializer can do.

Another use case is if you have a complex static variable that you need to initialize, but can't do in a single expression. For example, if you need to create multiple aggregated objects, you usually need multiple expressions. You can do this in a static initializer as well. Note that you can't set a static const within a static initializer, but you can set a static var (variables).

14 Responses to “Enums and ActionScript's Static Initializers”


  1. 1 Jared Rypka-Hauer

    Barney,

    It's pseudo-constructors for everyone, then, eh? :) Granted, post-classloading vs post-instantiation, but given that CF and AS3's paradigms are actually radically different, the analogy seems to resonate with me.

    J

  2. 2 barneyb

    Jared,

    The paradigms are totally incompatible.

    With a CFC, the psuedo-constructor just sits there, and when the CFC is instantiated, it gets invoked within the context of the new instance. The second time the CFC gets instantiated, it gets invoked again, again within the context of the new instance.

    With an AS class, the static initializer gets invoked when the class is loaded, with no instances of the class created. When the class is instantiated, the static initializer is NOT invoked again, only the constructor.

  3. 3 Jason Boyd

    Having seen several approaches to the Singleton case in AS3 (non-public class in constructor, using a random and/or private number, etc), this one works pretty well with minimal fuss:

    package foo
    {
    class Singleton
    {
    private static const m_instance:Singleton = new Singleton();

    public function Singleton()
    {
    if (m_instance != null) throw new Error("Noooooooo!!!!");
    // one time init code here
    }

    public static function getInstance():Singleton
    {
    return m_instance;
    }
    }
    }

    Static initializers are cool though. Thanks for the post!

  4. 4 barneyb

    Jason,

    The static initializer has a subtle benefit: no race condition. It's theoretically possible with the constructor-conditional method that two threads could instantiate objects at the same time and you end up with to singletons. Currently, the Adobe Flash player is single threaded so it's not actually possible, but that's an implementation detail.

    Because the static initializer happens at class load time, and you'll never see the same class loaded more than once, you're safe. A subtle point, and with the current implementation an irrelevant one, but still worth mentioning, I think.

  5. 5 Jason Boyd

    True and true. I tend to code all my AS3 assuming single threads, since AS3 is single-threaded. If they change this in AS4 or whenever, all bets are off.

  6. 6 Avangel

    Many thanks for this code trick :) I was trying to find solutions to emulate enums in AS3 for a while, without success. Your solutions is pretty good. It's a shame that AS does not enable protected/private contructors, it would have been even easier…

  7. 7 Jordan

    I think that I have found a better way to do it, you don't need the locked variable
    and with the "private" class in the constructor it can't be instantiated ,
    unless you pass null to the constructor , then runtime Error will occur :)!

    package {
    	final public class ColorEnum  {
    		//STATIC
    		public static const BLACK:ColorEnum = new ColorEnum(0x000000,null);
    		public static const WHITE:ColorEnum = new ColorEnum(0xFFFFFF,null);
    
    		//INSTANCE
    		private var _color:uint
    
    		public function get color():uint  {
    			return _color
    		}
    
    		function ColorEnum(color:uint,block_:block_constructor)  {
    			if (ColorEnum) throw new Error("You can't instantiate ColorEnum");
    			_color = color;
    		}
    	}
    }
    
    class block_constructor {}
    
  8. 8 Jason Boyd

    Amendment to the singleton pattern above. A runtime error on attempting instantiation might suprise users who's tools or docs show a plain old default constructor. Likewise requiring a "dummy" parameter of a private class is clunky. Not that this isn't…

    public class Foo {
    private static const MAGIC_NUM:Number = Math.random();
    private static const INSTANCE:Foo = new Foo(MAGIC_NUM);

    public function Foo(_magicNum) {
    if (_magicNum != MAGIC_NUM)
    throw new Error("Singleton, dummy!");
    }

    public function getInstance():Foo
    {
    return INSTANCE;
    }
    }

  1. 1 Static initializers in AS3
  2. 2 » typesafe enums in as3
  3. 3 » typesafe enum abstract class
  4. 4 ActionScript Enums « The Combined Corner
  5. 5 ActionScript 3 Enums « The Combined Corner
  6. 6 Enumerations with Class « Flex Insights

Leave a Reply