Enums - 열거형

Enums클래스와 다르며, 정해진 개수의 생성자 로 선언됩니다. 간단한 예제 :

    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;

            }
        }
    }

일정한 개수의 값만 사용하게 하려면, enum이 최적입니다. 왜냐하면 다른 값을 생성할 수 없도록 보장하기 때문입니다.

생성자 인자

위의 "Color" 샘플에서 하나의 enum 에 3개의 상수 생성자 가 있는 게 보일 겁니다. 또한 생성자에 인자가 있는 경우도 있습니다 :

    enum Color2 {
        Red;
        Green;
        Blue;
        Grey( v : Int );
        Rgb( r : Int, g : Int, b : Int );
    }

이 방법에서는 5개의 다른 생성자가 있지만, 무수히 많은 "Color2"가 생길 수 있습니다. 다음 값들은 모두 "Color2"에 해당합니다 :

    Red;
    Green;
    Blue;
    Grey(0);
    Grey(128);
    Rgb( 0x00, 0x12, 0x23 );
    Rgb( 0xFF, 0xAA, 0xBB );

또한, 재귀적인 형태가 있을 수도 있습니다. "alpha"를 추가한 예시 :

    enum Color3 {
        Red;
        Green;
        Blue;
        Grey( v : Int );
        Rgb( r : Int, g : Int, b : Int );
        Alpha( a : Int, col : Color3 );
    }

다음은 충분히 타당한 "Color3" 값입니다.

    Alpha( 127, Red );
    Alpha( 255, Rgb(0,0,0) );

enum이 고정적이라는 것을 명심해야 합니다. Enum의 인자는 이 읽기전용이기 때문입니다. 초기화 이후로 바뀔 수 없으며, 그럴 필요도 없습니다.

Enum과 switch문

switch에서 enum을 사용할 때, 특이하게 작동합니다. 만약, default가 없다면 모든 enum 생성자가 switch문에서 지정됐는지 확인하고, 만약 그렇지 않으면 컴파일러는 경고를 할 것 입니다. 가령, 처음에 나온 "Color" enum을 보면 :

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

이 경우에 생성자 "Blue"가 사용되지 않았다는 컴파일 에러가 발생할 겁니다. 이를 방지하려면 Blue를 사용한 case문를 추가하거나, default문을 추가해야 합니다. 새로운 생성자를 enum에 추가할 때마다, 컴파일 에러가 그 생성자를 명시해야하는 위치를 찾아 경고해주기 때문에, 상당히 유용할 수도 있습니다.

생성자 인자와 Switch

만약 enum 생성자가 인자를 가진다면, switch의 case에 변수이름을 반드시 명시해야 합니다. 여기서 모든 변수는 "case" 표현식 내에서 지역변수로 접근 가능하고, enum 생성자에서 정한 타입과 일치할 것 입니다. "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);
            }
        }

    }

switch를 사용하는 것은 enum 생성자 인자에 접근할 수 있는 유일한 방법입니다.

Enum 타입인자

또한, enum은 타입인자를 가질 수도 있습니다. 문법은 동일합니다. 타입인자로 연결된 List 예시:

    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);
            }
        }

    }

enum클래스 를 조합해 사용할 경우, 매우 강력한 결과를 낼 수도 있습니다.

인자에서 기본값으로 Enum을 사용하기

사실 enum 값은 생성자에서 만들어지기 때문에, 상수가 아닙니다. 그러므로 파라미터의 기본값으로 사용될 수 없습니다. 그러나 단순한 해결방법이 있습니다 :

    enum MyEnum {
        MyFirstValue;
        MySecondValue;
    }

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

문자열과 enum의 전환

문자열을 enum값으로 전환하려면 Type.createEnum() 메소드를 사용해야 합니다.

    enum EColor {
        Red;
        Green;
        Blue;
    }

    // 문자열로 전환 :
    var string = Std.string(EColor.Blue);

    // enum값으로 전환 :    
    var color:EColor = Type.createEnum(EColor, string);

Enum의 동일성 판단

두 enum이 동일한지 테스트하기 위해서는 Type.enumEq()를 사용해야 합니다. (연산자 ==는 불확실합니다. enum 생성자에는 인자가 없기 때문에, 이를 연산하려 하면 인자를 가져오려다 실패할 수 있습니다. 이런 혼란을 방지하기 위해, Type.enumEq()를 사용해야 합니다.)

또한, 비록 Type.enumEq가 생성자 인자를 확인한다 하더라도, 단순히 값만 같은지 확인할 뿐, 그 구조는 확인하지 않는 점을 주의해야 합니다. 예를 들어, enum 생성자 내의 Array는 그 안에 담긴 내용을 확인하지 않지만, 그 대신에 객체의 참조가 같은지 확인합니다. 구조적인 판단을 하려면 Pattern Matching 을 사용해야 합니다.

주의 및 특징

Haxe enum은 해당 메소드 결과의 모든 경우를 찾아내 지정할 수 있는 태그 조합과 유사하게 반응합니다. 모든 enum은 switch문에서 반드시 지정되어야 합니다. 그것은 해당 메소드의 결과을 모두 정의한다는 점, 이런 결과를 빠짐없이 다룬다는 점을 보장하기 떄문에 그 가치가 있습니다.

«« 타입 인자 - 패키지와 Import »»

version #19716, modified 2013-08-27 04:06:08 by papapang