Enumeration(열거형)은 연관된 항목들을 묶어서 표현할 수 있는 타입이다.
배열이나 딕셔너리와는 다르게 정의한 값 이외에 추가 또는 수정이 불가능하다.
따라서 다음과 같은 경우 잘 사용된다.
- 제한된 선택지를 주고 싶을 때
- 정해진 값 외에는 입력받고 싶지 않을 때
- 예상된 입력 값이 한정되어 있을 때
내가 공부하고 있는 책을 보면 위와 같이 나와있다.
사실 저렇게만 보면 잘 생각이 안될 수도 있는데, 책의 예시를 보면 이해가 잘 된다.
- ex) 무선통식 방식 : WiFi, Bluetooth, 5G, LTE, 3G, 기타
- ex) 학생 : 초등학생, 중학생, 고등학생, 대학생, 대학원생, 기타
- ex) 지역 : 서울, 경기도, 강원도, 경상도, 충청도, 전라도, 제주도
책에도 나와 있는데, 열거형은 switch 구문과 만났을 때 활용도가 매우 좋아진다.
이 부분은 switch에 대하여 정리할때 같이 정리하겠다.
열거형 선언은 아래와 같이 enum이라는 키워드로 한다.
import UIKit
enum School {
case elementary
case middle
case high
case university
case graduate
}
귀찮으면 아래와 같이 해도 된다.
import UIKit
enum School {
case elementary, middle, high, university, graduate
}
열거형 변수는 아래와 같이 생성할 수 있다.
var selectSchool: School = School.university
// 아래와 같이 university 앞에 School을 생략해도 된다.
var selectSchool: School = .university
위에 처럼 생성한 열거형 변수 selectSchool의 값으로는 School 내의 항목으로만 해줄 수 있다.
아래와 같이 School 내의 항목으로 값을 변경할 수 있다.
selectSchool: School = School.graduate
// 마찬가지로 아래와 같이 graduate 앞에 School을 생략해도 된다.
selectSchool: School = .graduate
열거형의 각 항목 자체는 하나의 값이다.
하지만 항목마다 Raw Value(원시 값)도 가질 수 있다.
Raw Value을 가지려면 아래와 같이 열거형 이름의 오른쪽에 타입을 명시하면 된다.
import UIKit
// String 타입으로 Raw Value 가짐
enum School: String {
case elementary = "유치원"
case middle = "중학교"
case high = "고등학교"
case university = "대학교"
case graduate = "대학원"
}
Raw Value 사용을 위해서는 rawValue 프로퍼티를 이용하면 된다.
아래와 같이 입력했을 경우의 결과를 보자.
📄 입력
import UIKit
enum School: String {
case elementary = "유치원"
case middle = "중학교"
case high = "고등학교"
case university = "대학교"
case graduate = "대학원"
}
var selectSchool: School = .graduate
print("저는 \(selectSchool.rawValue)에 재학 중 입니다.")
💻 출력
저는 대학원에 재학 중 입니다.
Raw Value를 일부만 주는 경우 Swift가 처리하는 방법이다.
만약 Raw Value가 String 타입이라면 그냥 항목 이름을 Raw Value로 갖는다.
예를 들어 다음과 같은 코드의 경우 university의 Raw Value는 "university"가 된다.
다음 입력과 출력을 참고하자.
📄 입력
import UIKit
enum School: String {
case elementary = "유치원"
case middle = "중학교"
case high = "고등학교"
case university
case graduate = "대학원"
}
print(School.university.rawValue)
💻 출력
university
만약 Raw Value가 Int 타입이라면 첫 항목을 기준으로 0부터 차례로 Raw Value로 갖는다.
예를 들어 다음과 같은 코드의 경우 eleven의 Raw Value는 어떻게 될까?
📄 입력
import UIKit
enum Nums: Int {
case zero
case one
case two
case ten = 10
case eleven
}
print(Nums.zero.rawValue)
print(Nums.one.rawValue)
print(Nums.two.rawValue)
print(Nums.ten.rawValue)
print(Nums.eleven.rawValue)
💻 출력
0
1
2
10
11
위와 같이 10의 다음 숫자인 11이 eleven의 Raw Value가 되는 것을 확인할 수 있다.
열거형 내의 항목은 자신과 연관된 Associated Value를 가질 수 있다.
가져도 되고 안가져도 된다.
Associated Value는 아래와 같이 열거형 내 각 항목 옆에 소괄호로 넣으면 된다.
import UIKit
enum Dish {
case pizza(dough: String, topping: String)
case salad(dressing: String)
case chicken(withSauce: Bool)
case friedrice
}
var myDish: Dish = Dish.salad(dressing: "balsamic") // 발사믹 드레싱 샐러드
위의 코드를 다시 보자.
보통 식당을 생각해보면 토핑이나 소스가 한정적이다.
따라서 토핑이나 소스도 열거형을 사용하면 좋다.
아래와 같이 열거형을 여러개 사용하여 나타내면 깔끔하다.
import UIKit
enum Dressing {
case balsamic, oriental, honeyMustard
}
enum Topping {
case cheese, pepperoni
}
enum Dish {
case pizza(dough: String, topping: Topping)
case salad(dressing: Dressing)
case chicken(withSauce: Bool)
case friedrice
}
var myDish: Dish = Dish.salad(dressing: Dressing.balsamic)
열거형의 모든 case들을 알아야하는 경우 CaseIterable 프로토콜을 활용하여 항목 순회를 할 수 있다.
열거형 뒤에 콜론을 찍고 CaseIterable을 채택하면 사용 가능하다.
이렇게 하면 열거형에 allCases라는 프로퍼티를 사용할 수 있는데, 이를 통해 항목 순회가 가능하다.
import UIKit
enum Nums: CaseIterable {
case zero
case one
case two
case ten
case eleven
}
let showNums: [Nums] = Nums.allCases
// => [zero, one, two, ten, eleven]
Raw Value가 있는 경우라면 아래와 같이 Raw Value의 타입 다음에 콤마를 찍고 CaseIterable을 써주면 된다.
import UIKit
enum Nums: Int, CaseIterable {
case zero
case one
case two
case ten = 10
case eleven
}
let showNums: [Nums] = Nums.allCases
@available 속성을 넣어 플랫폼 별로 사용 조건을 추가하는 경우 CaseIterable 프로토콜을 채택하는 것만으로 allCases 프로퍼티를 사용할 수 없을 수도 있다.
열거형의 case가 연관 값을 갖는 경우 역시 allCases 프로퍼티를 사용할 수 없다.
-> 위 두가지 경우에는 직접 allCases 프로퍼티를 구현해야한다.
순환 열거형은 열거형 항목이 열거형 자신의 값이고자 할 때 사용한다.
이를 명시하는 법은 indirect 키워드를 사용하는 것이다.
특정 항목에만 순환 열거형 항목을 명시하는 경우 아래와 같이 case 키워드 앞에 indirect 키워드를 사용하면 된다.
import UIKit
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
열거형 전체에 적용하고 싶다면, enum 키워드 앞에 indirect 키워드를 사용하면 된다.
import UIKit
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
Comparable 프로토콜을 준수하는 연관 값만 갖거나 연관 값이 없는 열거형은 Comparable 프로토콜 채택 시 각 case를 비교할 수 있다.
앞에 위치한 case가 더 작은 값이 된다.
아래와 같이 비교할 수 있다.
import UIKit
enum Condition: Comparable {
case terrible
case bad
case soso
case good
case great
}
let myCondition: Condition = .great
let yourCondition: Condition = .good
if myCondition > yourCondition {
print("My condition is better.")
}
else if myCondition < yourCondition {
print("Your condition is better")
}
else if myCondition == yourCondition {
print("We have same condition!")
}
else {
print("something wrong")
}
열거형은 잘 쓰면 정말 유용하게 쓸 수 있을 것 같은 개념이다.
뒤에 내용들을 정리하고 한번 더 추가로 정리할 것이 있으면 해야겠다.
개념 정리를 하니 확실히 깔끔하다.
앞으로 개념 정리를 소홀히 하지 말도록 노력해야지. 🙌✨