tutorials flash enumeration
[AS2 & AS3] Enumeration - Type-safe
General information
Enumerations are used more and more by developers to reduce redundancies in their code and to guarantee maximum safety. In ActionScript there are no set rules on this subject. There are therefore many different ways to use enumerations and I will try to show you my way of using them. My technique is mainly inspired by everything that I have gleaned from the AS3 framework, in frameworks like Pixlib and especially all that I have set up in VEGAS throughout its evolution.
1 - A simple example of enumeration using primitive types:
class ApplicationColor { public function getColor( color:Number ):Number { switch (color) { case 0xD97F00 : // apricot case 0xFFFFFF : // white case 0xD70079 : // fuscia case 0xAE293B : // cherry case 0xFF6633 : // coral return color ; default : return 0x000000 ; } } }
In the getColor () method above we can see firstly that the colour choice is not the most simple (unless you have a mixing palette in your head at all times), it is quite hard to precisely define the colors represented in the switch..case condition.
Moreover if we have to re-use these colours later in the code, we will have to take all of the primitives again each time… If during your development a colour changes you will need to set up a long refactoring to update the whole application.
It should be noted that I have however added some comments to make the code easier to read but this readability help stops there; it would be a pain to comment the code each time.
2 - A more evolved example with constants
class ApplicationColor { // ----o Constant Summary static public var APRICOT :Number = 0xD97F00 ; static public var WHITE :Number = 0xFFFFFF ; static public var FUSCIA :Number = 0xD70079 ; static public var CHERRY :Number = 0xAE293B ; static public var CORAL :Number = 0xFF6633 ; static public var BLACK :Number = 0x000000 ; static public function getColor( color:Number ):Number { switch (color) { case APRICOT : case WHITE : case FUSCIA : case CHERRY : case CORAL : return color ; default : return BLACK ; } } }
The code above is already much more clear. It is no longer necessary to comment it because the names of the enumerations are explicit. Moreover it is easy to modify a colour without having to change the whole of the code thereafter, you just need to use constants in all of the code and if you need to change a colour you can just redefine the value of one of the constants. This solution is much more elegant than the preceding one and remains quick and easy.
3 - "Typesafe" Enumeration.
We will now push the preceding example by integrating type-safe enumerations with a specific class for our colours.
class ApplicationColor extends Number { /** * Creates a new ApplicationColor */ public function ApplicationColor( value:Number ) { super(value) ; } // ----o Constant Summary static public var APRICOT :ApplicationColor = new ApplicationColor(0xD97F00) ; static public var WHITE :ApplicationColor = new ApplicationColor(0xFFFFFF) ; static public var FUSCIA :ApplicationColor = new ApplicationColor(0xD70079) ; static public var CHERRY :ApplicationColor = new ApplicationColor(0xAE293B) ; static public var CORAL :ApplicationColor = new ApplicationColor(0xFF6633) ; static public var BLACK :ApplicationColor = new ApplicationColor(0x000000) ; // ----o Public Method Summary static public function getColor( color:ApplicationColor ):Number { switch (color) { case APRICOT : case WHITE : case FUSCIA : case CHERRY : case CORAL : return color.valueOf() ; default : return BLACK.valueOf() ; } } }
The example above is a little more complex than the preceding example but it allows an improved security of the objects used.
Indeed, the enumerations are now type-safed with the ApplicationColor class which inherits the Number class and that ensures that the user will be able to dip into the colours of the application without making mistakes. It will be impossible for example to place in the getColor () method any other object other than an instance of the ApplicationColor class. Enumerations with primitive types (see example 2) are quick to set up but really lack security, in this case this problem is solved. It is now possible to apply an interesting design pattern that we call the “Type-safe Enum”. This pattern makes it possible to make the enumerations secure by using a private function constructor. It is therefore impossible to declare new instances of the class outside of this. Moreover by using a class to type-safe the enumerations it is possible to add to an implementation to them with interfaces or functionalities using easier methods than with a primitive type. Let us look closer at a finished version of our ApplicationColor class with an example in AS2:
class ApplicationColor extends Number { /** * Creates a new ApplicationColor */ private function ApplicationColor( value:Number, name:String ) { super(value) ; this.name = name ; } // ----o Constants static public var APRICOT :ApplicationColor = new ApplicationColor(0xD97F00, "apricot") ; static public var WHITE :ApplicationColor = new ApplicationColor(0xFFFFFF, "white") ; static public var FUSCIA :ApplicationColor = new ApplicationColor(0xD70079, "fuscia") ; static public var CHERRY :ApplicationColor = new ApplicationColor(0xAE293B, "cherry") ; static public var CORAL :ApplicationColor = new ApplicationColor(0xFF6633, "coral") ; static public var BLACK :ApplicationColor = new ApplicationColor(0x000000, "black") ; static private var __ASPF__ = _global.ASSetPropFlags(ApplicationColor, null, 7, 7) ; // ----o Public Properties public var name:String = null ; // ----o public methods static public function getColor( color:ApplicationColor ):Number { switch (color) { case APRICOT : case WHITE : case FUSCIA : case CHERRY : case CORAL : return color.valueOf() ; default : return BLACK.valueOf() ; } } public function toString():String { return this.name ; } }
Positive points to this pattern
- The constructor is private and it is impossible to create new enumerations outside of the class.
- The use of ASSetPropFlags allows you to transform the static properties into constants, it is impossible to remove or modify the enumerations.
- I overwrite the toString () method of the class to send back the instance name and the valueOf () returns the numerical value of the instance which allows you to combine at the same time classic manipulations with operators of these enumerations but also to return more explicit messages in the output window (I personally prefer reading the word “apricot” in my output window compared to the value 14253824 which corresponds to it in base 10). Negative points of this pattern:
The main negative point in my opinion is that this technique weighs down your applications and can take some time to set up compared to a simple primitive variable. It is certain that when we start to use this kind of technique we lose some “speed”. These techniques are however used within complex frameworks and require careful attention to the code’s architecture.
Remarks
1 - The use of the constants written as above using only capital letters remain very much used in the development community of ActionScript, ECMAScript or even JAVA etc… 2 - In AS3 it is not possible to use a private constructor (there is a lot of discussion on this subject for example with Singleton’s pattern concept) but it is possible to use exceptions to secure the function’s constructor. It is also possible to use a simple “object”. (It will be interesting to see whether Adobe will make the constructor private or not in the next updates to the AS3 framework at the launch of Flash9 or Apollo? I think that this will depend on the decisions taken with the final version of ECMASCript version 4.)
Resources
- A good article on this subject is on Darron Schall’s blog : Enumerated Types in ActionScript with a link to reserved keywords for the future version 4 of the ECMAscript, where we can clearly see that the keyword enum may appear in the next versions of ActionScript.
By ALCARAZ Marc aka EKAMELEON (2006). You can find this tutorial and comments on the subject on my blog.
Mediabox Training Centre © 2000 - 2008 All rights reserved.
Adobe Authorized Training Centre. State convention under number 25 14 02167 14.
Mediabox : SARL au capital de 62.000€ - Activity number: 25 14 02167 14 - SIRET : 493 716 468 00027
MEDIABOX, 102 Avenue des Champs Elysées, 75008 PARIS - Tel. +33(0)2.31.91.96.89 - Fax. +33(0)2.72.68.56.42


