Enums

Enums are different from 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's possible, but there 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) );

Note that enums are immutable, which means the parameters of an Enum are read-only. We cannot and should not change it after initialization.

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 an enum's constructors are used within the switch, and if not the compiler will generate a warning. For example, consider the first Color enum :

    switch( c ) {
        case Red: 0xFF0000;
        case Green: 0x00FF00;
    }

This will cause a compile errorwarning that the constructor blue is not used. In this example you can either add a case for it or add a default case that does something. This can be quite useful, as when you add new constructors to your enum, compiler errors will alert you to areas in your program where the new constructor should be handled.

Switch with Constructor Parameters

If enum constructors 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

An Enum 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 cellLength(head);
        }

        private function cellLength( c : Cell<T> ) : Int {
            return switch( c ) {
            case Empty : 0;
            case Cons(item,next): 1 + cellLength(next);
            }
        }

    }

Using both enums and classes together can be pretty powerful in some cases.

Using Enums as default value for parameters

Because an Enum's values are in fact created from a constructor they are not constant and therefore cannot be used as default value for a parameter. However there's a simple work-around :

    enum MyEnum {
        MyFirstValue;
        MySecondValue;
    }

    class Test {
        static function withDefaultValuesOnParameters(?a : MyEnum) {
            if(a == null)
                a = MyEnum.MyFirstValue;
        }
    }

Enums to and from strings


Use Type.createEnum() method to recreate an enum value from a string:
    enum EColor {
        Red;
        Green;
        Blue;
    }

    // To string:
    var string = Std.string(EColor.Blue);

    // From string:        
    var color:EColor = Type.createEnum(EColor, string);

Enum Equality

Use Type.enumEq() to test for equality between two enums. (Operator == is not guaranteed, empirically will work for enum constructors that take no arguments, but can fail for those taking arguments. All of which can lead you astray: use Type.enumEq() to be correct.)

Also note, that even though Type.enumEq checks constructor arguments, it does it by simply checking value equality, not by structure, so, for example, arrays in enum constructors won't be checked by content, but by object reference instead. Use Pattern Matching for structural checking.

Note


Haxe Enums behave very similarly to tagged unions, enabling the specification and capture of every "case" of a given method result. Since all Enum states must be specified in switch statements, this makes them valuable in completely defining the behavior of a given method, as well as ensuring that these behaviors are handled.

«« Type Parameters - Packages and Imports »»

version #19584, modified 2013-07-17 08:52:01 by nadako