열거형

열거형은 정수 값의 집합입니다. 각 값은 대응되는 이름을 갖습니다.

enum Color
  Red
  Green
  Blue
end

열거형은 enum 예약어 뒤에 이름을 써서 정의합니다. 열거형의 본체에 값이 올 수 있습니다. 값은 0으로 시작하여 하나씩 증가합니다. 이 기본값을 덮어쓸 수도 있습니다.

enum Color
  Red         # 0
  Green       # 1
  Blue   = 5  # 5로 덮어씀
  Yellow      # 6 (5 + 1)
end

열거형의 각 상수는 그 열거형의 타입을 갖습니다.

Color::Red #:: Color

value를 호출하여 기저에 있는 값을 얻어올 수 있습니다.

Color::Green.value #=> 1

그 값은 기본적으로 Int32이지만, 타입을 바꿀 수도 있습니다.

enum Color : UInt8
  Red
  Green
  Blue
end

Color::Red.value #:: UInt8

기저 타입으로는 정수 타입만을 사용할 수 있습니다.

모든 열거형은 Enum을 상속합니다.

플래그 열거형

열거형에 @[Flags] 속성을 지정하여 기본값을 바꿀 수 있습니다.

@[Flags]
enum IOMode
  Read # 1
  Write  # 2
  Async # 4
end

@[Flags] 속성은 첫 상수의 값을 1로 바꾸고, 뒤에 오는 값을 2씩 곱합니다.

암묵적인 NoneAll 상수가 열거형에 자동으로 추가됩니다. None의 값은 0이며 All의 값은 모든 상수에 비트 OR 연산을 한 값이 됩니다.

IOMode::None.value #=> 0
IOMode::All.value  #=> 7

또한 Enum의 몇 가지 메서드를 사용하기 위해서는 @[Flags] 속성이 필요합니다.

puts(Color::Red)                    # "Red"를 출력
puts(IOMode::Write | IOMode::Async) # "Write, Async"를 출력

정수에서 열거형으로의 변환

정수로부터 열거형을 생성할 수 있습니다.

puts Color.new(1) #=> "Green"을 출력

열거형의 상수 중에 없는 값은 사용할 수 없습니다. 타입은 Color가 되겠지만, 출력해 보면 기저에 있는 값이 그대로 사용되는 것을 알 수 있습니다.

puts Color.new(10) #=> "10"을 출력

이 메서드는 C에서의 정수를 크리스탈의 열거형으로 변환하는 것이 주 목적입니다.

메서드

클래스나 구조체와 마찬가지로 열거형에서 메서드를 정의할 수 있습니다.

enum Color
  Red
  Green
  Blue

  def red?
    self == Color::Red
  end
end

Color::Red.red?  #=> true
Color::Blue.red? #=> false

인스턴스 변수는 정의할 수 없고, 클래스 변수만을 정의할 수 있습니다.

사용

열거형은 Symbol의 타입 안정성을 확보한 대안입니다. 예를 들어, API의 메서드에서 열거형을 이용한 타입 제약을 특정할 수 있습니다.

def paint(color : Color)
  case color
  when Color::Red
    # ...
  else
    # 확률은 높지 않아도 일어날 수 있음
    raise "알 수 없는 색깔: #{color}"
  end
end

paint Color::Red

위의 예시를 Symbol로 구현할 수도 있습니다.

def paint(color : Symbol)
  case color
  when :red
    # ...
  else
    raise "알 수 없는 색깔: #{color}"
  end
end

paint :red

하지만 프로그래머가 :reed 같은 오타를 낸다면 실행 시간에나 오류를 알아차릴 수 있습니다. 하지만 Color::Reed는 컴파일 오류이므로 컴파일 시간에 알아차릴 수 있습니다.

가능하다면 열거형은 사용하는 것이 권장됩니다. 심볼은 API의 내부 구현에서만 사용하고 공개 API에서는 심볼을 가급적이면 피해야 합니다. 그렇다고 굳이 심볼을 쓰는 것을 말릴 사람이 있는 것은 아닙니다.

results matching ""

    No results matching ""