Swift Collection - 열거형
열거형은 연관된 항목들을 묶어서 표현할 수 있는 타입으로, 프로그래머가 정의해준 값 외에는 추가나 수정이 불가능하다. 그렇기 때문에 딱 정해진 값만 열거형 값에 속할 수 있다.
열거형은 다음과 같은 상황에 유용하게 사용할 수 있다.
- 제한된 선택지를 주고 싶을 때
- 정해진 값 외에는 입력받고 싶지 않을 때
- 예상된 입력 값이 한정되 있을 때
즉 연관된 값들을 높은 가독성으로 나열하는데 특화되있으며, 실생활에서 이미 열거형으로 사용할 수 있는 개념들이 많다. 예를 들어 요일은 [월요일,화요일,수요일,목요일,금요일,토요일,일요일] 으로만 이루어져 있기 때문에, 이것을 열거형으로 만들면 해당 API 를 사용하는 프로그래머는 무조건 정의된 요일만 사용할 수 있다.
기본 열거형
스위프트의 기본 열거형은 enum 이라는 키워드로 선언할 수 있으며, 각 열거형은 이름을 가질 수 있다.
enum Day {
...
}
그리고 열거형의 각 데이터는 case 키워드로 선언할 수 있으며, 한 줄에 모두 표현할 수 있다.
enum Day {
case Monday
case Tuesday
case Wednesday
case Thursday
case Friday
case Saturday
case Sunday
}
//or
enum Day {
case Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
}
스위프트의 열거형은 다음과 같이 사용할 수 있다.
var currentDay : Day = Day.Monday
var tomorrow = Day.Tuesday //타입 추론
var yesterday :Day = .Sunday //열거형의 타입을 정해줌
원시 값
열거형의 각 항목은 원시 값을 가질 수 있다. 특정 원시 값을 가지고 싶다면 열거형 이름 타입 오른쪽에 다음과 같이 타입을 명시해주면 된다.
enum Day : Int {
case Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
}
or
enum Day : Int {
case Monday = 0,Tuesday = 1,Wednesday = 2,Thursday = 3,Friday = 4,Saturday = 5,Sunday = 6
}
raw Value 의 타입을 저렇게 할당해줄 수 있으며, 아래와 같이 열거형.rawValue 라는 프로퍼티를 사용해 값을 가져올 수도 있다.
enum Day : Int {
case Monday = 0,Tuesday = 1,Wednesday = 2,Thursday = 3,Friday = 4,Saturday = 5,Sunday = 6
}
print(Day.Monday.rawValue)
//출력 결과
0
원시 타입을 지정해줬다고 해서, 모든 열거형에 값을 지정할 필요가 없다. 값을 지정하지 않아도 컴파일러가 알아서 처리해주며, 문자열을 원시 타입으로 지정해주면 각 항목의 이름을, 정수를 지정해주면 0 부터 순서대로 1씩 늘어난 값을 원시형으로 갖게 된다.
즉 위 코드에서 열거형에 값을 할당해주지 않더라도 Monday 의 rawValue 는 0이 된다는 소리다
또한 rawValue 를 가지고 열거형을 얻을 수 있다. Monday 의 rawValue 는 0이기 때문에, 0으로 Monday 를 가져올 수 있다.
enum Day : Int {
case Monday = 0,Tuesday = 1,Wednesday = 2,Thursday = 3,Friday = 4,Saturday = 5,Sunday = 6
}
var currentDay = Day(rawValue: 0)
var what = Day(rawValue: 10) //만약 10인 rawValue 를 가지는 열거형이 없으면, nil 이 된다!
연관 값
열거형은 관련된 연관값을 가질 수 있다. 각 열거형마다 관련된 값을 소괄호로 묶어 표시할 수 있으며, 다른 항목이 연관값을 가진다고 해서 무조건 모든 항목이 가질 필요는 없다.
음식점을 예로 들어보자. 음식점은 피자를 전문으로 팔며, 하와이안 피자, 오리지널 피자, 불고기 피자를 판매한다. 또 각 피자를 주문할 때 갈릭 소스, 핫소스, 달콤소스를 선택할 수 있다.
우리는 위 정보를 가지고 두 가지의 열거형을 만들 수 있다.
enum Pizza {
case HawaianPizza
case OriginalPizza
case BulgogiPizza
}
enum Sauce{
case Garlic
case Hot
case Sweet
}
각 피자를 주문할 때 손님이 소스를 선택할 수 있기 때문에, 소스를 피자의 연관값으로 추가시켜보자!
enum Pizza {
case HawaianPizza(sauce:Sauce)
case OriginalPizza(sauce:Sauce)
case BulgogiPizza(sauce:Sauce)
}
enum Sauce{
case Garlic
case Hot
case Sweet
}
이제 우리가 Pizza 타입의 변수를 생성할 때 다음과 같이 생성할 수 있다.
let MyPizza : Pizza = .OriginalPizza(sauce: .Hot)
let disgustingPizza = Pizza.HawaianPizza(sauce: .Garlic)
Switch 와 함께 사용하기
Swift 의 열거형은 switch 문과 함께 사용하면 더욱 강력해진다. 내가 주문한 피자가 뭔지 알고 싶다면, 다음 코드를 살펴보자
let MyPizza : Pizza = .OriginalPizza(sauce: .Hot)
let disgustingPizza = Pizza.HawaianPizza(sauce: .Garlic)
switch MyPizza {
case .HawaianPizza(sauce: _):
print("내가 선택한 피자는 하와이안 피자입니다. 소스는 아무거나 상관없습니다. 정말 싫은 피자네요")
case .OriginalPizza(sauce: let sauce):
print("내가 선택한 피자는 오리지널 피자로, 소스는 \(sauce)입니다")
case .BulgogiPizza(.Garlic):
print("내가 선택한 피자는 불고기 피자로, 소스는 무조건 갈릭 소스여야 합니다.")
default:
print("몰라")
}
우선 switch 문의 첫 번째 케이스를 보자. 우리가 Pizza 열거형에 소스라는 연관값을 추가했으므로, 이 열거형을 switch 문으로 판별할 때 소스에 대한 정보도 필요하다. 이 때 아무 소스를 가진 하와이안 피자를 해당 케이스로 진입하게 하고 싶다면, 연관값에 _ 를 사용해서 연관값을 무시할 수 있다.
두 번째 케이스는 OriginalPizza 일 때 진입할 수 있으며, 소스에 대한 정보를 내가 접근해야 할 때 사용할 수 있다. let 을 통해 실제 소스 값과 바인딩 시켜줄 수 있으며, sauce 상수를 사용해 데이터에 접근할 수 있다.
세 번째 케이스는 오로지 갈릭 소스만 가진 불고기 피자로만 접근할 수 있다.
if 문과 함께 사용하기
if case Pizza.HawaianPizza(sauce: let sauce) = MyPizza {
print(sauce)
}
if case Pizza.HawaianPizza(sauce: _) = MyPizza {
print("하와이안 피자입니다.")
}
if case Pizza.OriginalPizza(sauce: Sauce.Hot) = MyPizza {
print("내가 선택한 피자는 오리지널 핫소스 피자입니다.")
}
if문과도 마찬가지로 사용할 수 있으며, 위와 같이 연관값을 바인딩하거나, 무시하거나, 지정해서 받을 수 있다.