Enumeration 정리

Enumeration, 열거형은 경우를 한정할 때 많이 쓰이는 타입으로 프로젝트를 하면서 경우를 명시적으로 정하고 싶을 때 써 본 경험이 있다. 하지만 열거형을 더욱 유용하게 쓸 수 있는 원시 값(Raw Value), 연관 값(Associated Value)은 정확히 알지 못해 정리해보려 한다. 정리는 야곰 님의 스위프트 프로그래밍을 토대로 하였다.

열거형이란?

열거형은 연관된 항목을 묶어서 표현할 수 있는 타입이다. 배열이나 딕셔너리와 달리 프로그래머가 정의해준 항목 값 외에는 항목의 추가/수정이 불가능한다. 다음은 열거형이 유용하게 쓰일 수 있는 경우이다.

  • 제한된 선택지를 주고 싶을 때
  • 정해진 값 외에는 입력받고 싶지 않을 때
  • 예상된 입력 값이 한정되어 있을 때

Swift는 다른 보통의 언어와 달리 열거형의 각 항목이 값을 가질 수도, 갖지 않을 수도 있다. C 같은 경우 정수형의 값들에 별칭을 달아 놓은 것일뿐이지만 Swift는 열거형 그 자체가 고유한 타입으로 인식된다.

기본적인 열거형

기본적인 열거형은 다음과 같이 선언하고 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum PokemonType {
case fire
case water
case grass
case dragon
case normal
}

class Pokemon {
let type: PokemonType

init(type: PokemonType) {
self.type = type
}
}

let bulbasaur = Pokemon(type: PokemonType.grass)
let charmander = Pokemon(type: .fire)

원시 값(Raw Value)

열거형은 각 항목마다 값을 가질 수도 있는데 이를 원시 값(Raw Value)라고 한다. 원시 값을 가지려면 그 값에 맞는 타입을 열거형의 이름 옆에 명시적으로 적어주면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
enum PokemonType: String {
case fire = "불 타입"
case water = "물 타입"
case grass = "풀 타입"
case normal = "노말 타입"
case dragon
}

let charmander = Pokemon(type: .fire)
print("파이리의 타입은 \(charmander.type.rawValue)입니다.")
// 파이리의 타입은 불 타입입니다.
let normalType = PokemonType(rawValue: "노말 타입")
if let normalType = normalType {
let snorlax = Pokemon(type: normalType)
print("잠만보의 타입은 \(snorlax.type.rawValue)입니다.")
// 잠만보의 타입은 노말 타입입니다.
}

let dragonite = Pokemon(type: .dragon)
print("망나뇽의 타입은 \(dragonite.type.rawValue)입니다.")
// 망나뇽의 타입은 dragon입니다.

원시 값을 가져올 때는 rawValue 프로퍼티로 가져오면 된다. 만약 원시 값을 알고 있을 경우에는 원시 값으로 열거형 변수/상수를 선언할 수 있다. 이 때 원시 값이 맞지 않는 경우에 nil이 되는 실패 가능한 초기화이므로 위의 예제에서는 언래핑 후 사용한 것을 볼 수 있다.

원시 값이 주어지지 않았을 경우 String 타입은 항목의 이름을, Int 타입이라면 첫 항목을 기준으로 0부터 1씩 늘어난 값을 원시 값으로 가진다.

연관 값(Associated Value)

Swift에서는 열거형의 각 항목에 자신과 연관된 값을 가질 수 있다. 연관 값은 각 항목 옆에 괄호를 붙여서 표현한다. 원시 값과 마찬가지로 모든 항목이 연관 값을 가질 필요는 없다.

1
2
3
4
5
6
7
8
9
10
11
enum Beverage {
case coke
case cider
case fanta
}

enum Food {
case burrito(isCheese: Bool, beverage: Beverage)
case burger
case pizza(topping: String)
}

Reference