I am preparing an article about this pattern in Java. I found the necessary material and understood that the article was quite voluminous and I could not write it right away. Therefore, I decided to write about this pattern in Flash and look at the reaction of the community.Enumerations is a set of values ββ(elements) that are close in meaning. For example:
- Light directions - north (north), south (south), east (east), west (west)
- Type of novel - mystery, classic, fantasy, romance, science-fiction
- flavors of ice cream - chocolate, vanilla, raspberry, maple
Previously, the standard solution for representing enumerated types was the int Enum pattern:
// int Enum Pattern - has severe problems! public static const SEASON_WINTER : Number = 0; public static const SEASON_SPRING : Number = 1; public static const SEASON_SUMMER : Number = 2; public static const SEASON_AUTUMN : Number = 3;
This pattern has many flaws. We will try to list some:
- Not typesafe - In those places where the season is expected, you can insert any other int value, or, for example, add two seasons, which does not make sense.
- No namespace β It is necessary to use a prefix for constants (in our example, SEASON_) in order to avoid collisions with other sets of constants.
- Printed values ββare uninformative - Due to the fact that the values ββof constants are just integer values, when they are output to the console (screen, file, etc.), just the value will be displayed, which does not tell anything about the purpose of this constant and about her type.
The essence of this pattern is as follows:
- static constants of a certain type are created (Enum type)
- The constructor of this type takes the value that it will wrap.
- This type must have a method that returns a wrapped value.
An example for our seasons might look like this:
')
package { public class Season { // . public static const WINTER : Season = new Season("winter"); public static const SPRING : Season = new Season("spring"); public static const SUMMER : Season = new Season("summer"); public static const AUTUMN : Season = new Season("autumn"); private static var _enumCreated:Boolean = false; // magic happens here, the static code block { _enumCreated = true; } private var _seasonName : String; public function Season(seasonName : String) { if (_enumCreated) throw new Error("The enum is already created."); _seasonName = seasonName; } public function get seasonName() : String { return _seasonName; } } }
Usage example
// public function traceSeason(season : Season) { trace(season.seasonName); } traceSeason(Season.WINTER);
Using this pattern, we can not be afraid that an unpredictable value will be passed to our method. For nothing else but Season can be transferred to the method.
It is worth noting that in the classical implementation of this pattern, the construct must be private. But alas, ActionScript 3.0 does not support this. Of course, you could use the nested class. But, in my opinion, this method is not very beautiful (more details can be found in the article
Options for implementing the Singleton pattern in ActionScript 3 ).
There is a more "elegant" solution (by the way, it is given in the example). AS3 introduces the concept of a static initialization block. The code that is located in this block is executed when the class is loaded into memory. This happens before the constructor is called, but, at the same time, after all the static variables of the class are initialized. Thus, by setting the class instance creation permission flag, we can restrict access to the constructor. We describe the order of actions performed during this:
- Our class is loaded into memory.
- Static variables are initialized.
- _enumCreate becomes false (default value)
- The first static constant WINTER is created. Because _enumCreate is false, then an instance of this class is beautifully created.
- The second is being created ....
- A static initialization block is executed, in which the _enumCreated variable
set to true. This eliminates the possibility of "manually" creating an instance of the Season class. - TA-dah. Class loaded :)
And also, if you want to show something meaningful at trace (Season), then simply overload the toString () method.
Sources: