Enums
Enums are different than classes and are declared with a finite number of constructors. Here's a small example:
enum Color { red; green; blue; } class Colors { static function toInt( c : Color ) : Int { return switch( c ) { case red: 0xFF0000; case green: 0x00FF00; case blue: 0x0000FF; } } }
When you want to ensure that only a fixed number of values are used then enums are the best thing since they guarantee that other values cannot be constructed.
Constructors parameters
The previous Color sample shows three constant constructors for an enum. It is also possible to have parameters for constructors :
enum Color2 { red; green; blue; grey( v : Int ); rgb( r : Int, g : Int, b : Int ); }
This way, there is an infinite number of Color2 possible, but they are five different constructors possible for it. The following values are all Color2 :
red;
green;
blue;
grey(0);
grey(128);
rgb( 0x00, 0x12, 0x23 );
rgb( 0xFF, 0xAA, 0xBB );
We can also have a recursive type, for example to add alpha :
enum Color3 { red; green; blue; grey( v : Int ); rgb( r : Int, g : Int, b : Int ); alpha( a : Int, col : Color3 ); }
The following are valid Color3 values :
alpha( 127, red ); alpha( 255, rgb(0,0,0) );
Switch on Enum
A switch has a special behavior when used on an enum. If there is no default case then it will check that all enum constructor are used, and you'll get an error if not. For example, consider the first Color enum :
switch( c ) { case red: 0xFF0000; case green: 0x00FF00; }
This will cause an compile error telling that the constructor blue is not used. In that case you can either add a case for it or add a default case that does something. It's very useful since when you add a new constructor to your enum, compiler errors will display in your program the places where the new constructor have to be handled.
Switch with Constructor Parameters
If enum constructor have parameters, they must be listed as variable names in a switch case. This way all the variables will be locally accessible in the case expression and correspond to the type of the enum constructor parameter. For example, using the Color3 enum :
class Colors { static function toInt( c : Color3 ) : Int { return switch( c ) { case red: 0xFF0000; case green: 0x00FF00; case blue: 0x0000FF; case grey(v): (v << 16) | (v << 8) | v; case rgb(r,g,b): (r << 16) | (g << 8) | b; case alpha(a,c): (a << 24) | (toInt(c) & 0xFFFFFF); } } }
Using switch is the only possible way to access the enum constructors parameters.
Enum Type Parameters
Enum, as classes, can also have type parameters. The syntax is the same so here's a small sample of a parameterized linked List using an enum to store the cells :
enum Cell<T> { empty; cons( item : T, next : Cell<T> ); } class List<T> { var head : Cell<T>; public function new() { head = empty; } public function add( item : T ) { head = cons(item,head); } public function length() : Int { return cell_length(head); } private function cell_length( c : Cell<T> ) : Int { return switch( c ) { case empty : 0; case cons(item,next): 1 + cell_length(next); } } }
Using both enum and classes together can be pretty powerful in some cases.
Using Enums as default value for parameters
Because Enums' values are in fact created from a constructor they are not constant and therefore cannot be used as default value for a parameter. But there's a simple work-around :
enum MyEnum { myFirstValue; mySecondValue; } class Test { static function withDefaultValuesOnParameters(?a : MyEnum) { if(a == null) a = MyEnum.myFirstValue; } }
«« Type Parameters - Packages and Imports »»