Implementing Enumerated Types in ActionScript 3

UPDATE I’ve improved on this implementation; please see the later post The Arrogant Enum.

This is about implementing an enum in AS3 with value restriction ( i.e. the programmer should be unable to diminish or add to the set of values) and type safety.

We’ll implement the data type as a Class. In order to keep the programmer from adding to the set of values, we need to disallow invocation of the constructor.

Back when AS3 came out, there was much talk about the lack of private constructors and what to do about it, especially with regard to implementing the Singleton pattern. My favorite of the solutions is to define a file-level class and require it (the class, not an instance!) as a constructor parameter.

From there we can proceed just as Daniel Savarese describes in Implementing Enumerated Types in Java.

I don’t show how to implement an ordering on the enum values. See the Savarese article for that, too.

package
{
	import flash.errors.IllegalOperationError;
	
	public final class PailContents
	{
		public static const WATER:PailContents = new PailContents(PrivateConstructorEnforcer, "water");
		public static const CHICKENFEED:PailContents = new PailContents(PrivateConstructorEnforcer, "chicken feed");
		public static const MILK:PailContents = new PailContents(PrivateConstructorEnforcer, "milk");
		public static const OATS:PailContents = new PailContents(PrivateConstructorEnforcer, "oats");

		private var _name:String;
	
		public function PailContents(lock:Class, name:String)
		{
			super();
			if (lock != PrivateConstructorEnforcer)
			{
				throw new IllegalOperationError("Invalid constructor access");
			}
			_name = name;
		}

		// don't forget to implement toString() to support implicit conversion to String for trace() etc:
		public function toString():String
		{
			return _name;
		}

	}
}

// defined outside the package, and therefore visible only within this source file:
class PrivateConstructorEnforcer {}
  • http://www.jacksondunstan.com Jackson Dunstan

    I really like this technique, especially because you don’t need to instantiate the PailContents for each enum object you need. This means you can skip the expensive constructor and keep the number of objects limited to the number of enum values. One thing though: when implementing singletons via a pseudo-private constructor as you have I prefer this approach:

    class Classy
    {
    private static const SINGLETON_ENFORCER:Object = {};
    public function Classy(enforcer:Object, …)
    {
    if (enforcer != SINGLETON_ENFORCER)
    {
    throw new IllegalOperationError(…);
    }
    }
    }

    It’s very close to what you have, but means that you don’t need to create a whole class to enforce the “private” constructor but instead simply a static variable and an empty Object. This saves a little on SWF size and may even be a little quicker, though I haven’t tested this and the error case is certainly not a performance-critical path. :)

    Thanks for the link and for posting your AS3 version of the technique!

  • alan

    Thanks, Jackson. I don’t often discuss efficiency and optimization, and often it’s at odds with making the code “cleaner.”

    I’m in the midst of catching up on your blog, which is a must-read for AS3 programmers.

  • Pingback: Strategies For Global Data ( hey it happens… )- Touch My Blog

  • alan

    I am now officially preferring Jackson’s approach in comment #1, not only for the reasons he gives, but because by making that ENFORCER Object protected, I’m able to implement enumerated subtypes! More on this at a later date…

A sample text widget

Etiam pulvinar consectetur dolor sed malesuada. Ut convallis euismod dolor nec pretium. Nunc ut tristique massa.

Nam sodales mi vitae dolor ullamcorper et vulputate enim accumsan. Morbi orci magna, tincidunt vitae molestie nec, molestie at mi. Nulla nulla lorem, suscipit in posuere in, interdum non magna.