열거형은 연관된 항목들을 묶어서 표현할 수 있는 타입이다. 열거형은 아래와 같은 경우 사용하면 좋다.
ex) 열거형의 선언
enum School1{
case primary
case elementary
case middle
case high
case college
case university
case granduate
}
enum School2{
case promary, elemetary, middle, high, college, university, granduate
}
ex) 열거형 변수의 생성 및 값 변경
var highestEducationLevel: School = School .university
//위와 같은 표현
var highestEducationLevel: School = .university
//같은 타입인 School 내부의 항목으로만 highestEducationLevel의 값을 변경해줄 수 있다.
highestEducationLevel = .primary
열거형의 각 항목은 자체로도 하나의 값이지만 항목의 원시 값도 가질 수 있다.
즉, 특정 타입으로 지정된 값을 가질 수 있다는 뜻이다.
원시 값을 사용하려면 rawValue를 사용하면 된다.
ex) 원시 값
enum School: String{
case primary = "유치원"
case elementary = "초등학교"
case middle = "중학교"
case high = "고등학교"
case college = "대학"
case university = "대학교"
case granduate = "대학원"
}
let highestEducationLevel: School = School.university
print("최종학력은 \(highestEducationLevel.rawValue) 졸업")
enum WeekDays: Character{
case mon="월", tue="화", wed="수", thu="목", fri="금", sat="토", sun="일"
}
let today: WeekDays = WeekDays.fri
print("오늘은 \(today.rawValue)요일")
일부의 항목만 원시 값을 줄 수 있다.
문자열 형식의 원시 값을 지정했다면 각 항목의 이름을 그대로 원시 값으로 갖게 되고,
원시 값의 형식이 정수라면 첫 항목을 기준으로 0부터 1씩 더한 값을 갖게 된다.
ex) 원시 값 일부 지정
enum School: String{
case primary = "유치원"
case elementary = "초등학교"
case middle = "중학교"
case high = "고등학교"
case college
case university
case granduate
}
let highestEducationLevel: School = School.university
print(highestEducationLevel) //univeersity
print(School.elementary.rawValue) //초등학교
enum Numbers: Int{
case zero, one, two, ten=10
}
print(Numbers.zero.rawValue)//0
print(Numbers.one.rawValue)//1
print(Numbers.two.rawValue)//2
print(Numbers.ten.rawValue)//10
ex) 원시 값을 통한 열거형 초기화
let primary = School(rawValue: "유치원")//primary
let graduate = School(rawValue: "석박")//nil
let one = Numbers(rawValue: 1)//one
let three = Numbers(rawValue: 3)//nil
열거형 내의 항목이 자신과 연관된 값을 가질 수 있다.
연관 값은 각 항목 옆에 소괄호로 묶어 표현할 수 있다.
일부의 항목만 연관 값을 가지게 할 수 있다.
ex) 열거형 - 연관 값
enum Maindish{
case pasta(taste: String)
case pizza(dough:String, topping:String)
case chicken(withSauce: Bool)
case rice
}
var dinner: Maindish = Maindish.pasta(taste: "크림")
print(dinner) // pasta(taste: "크림")
dinner = .pizza(dough: "리치골드", topping: "포테이토")
dinner = .chicken(withSauce: true)
dinner = .rice
ex) 열거형 응용
enum PastaTaste{
case cream, tomato
}
enum PizzaDaugh{
case cheeseCrust, thin, richgold
}
enum PizzaTopping{
case pepperoni, potato, chicken
}
enum Maindish{
case pasta(taste: PastaTaste)
case pizza(dough:PizzaDaugh, topping:PizzaTopping)
case chicken(withSauce: Bool)
case rice
}
var dinner: Maindish = Maindish.pasta(taste: PastaTaste.tomato)
dinner = Maindish.pizza(dough: PizzaDaugh.thin, topping: PizzaTopping.potato)
열거형에 포함된 모든 케이스를 알고 싶을 때 CaseIterable을 사용한다.
그러고 나서 allCases를 사용하여 모든 케이스의 컬렉션을 생성할 수 있다.
ex) 항목 순회 - CaseIterable
enum School: CaseIterable{
case primary
case elementary
case middle
case high
case college
case university
}
let allCases: [School] = School.allCases
print(allCases)
ex) 항목 순회 - 원시 값
enum School: String, CaseIterable{
case primary = "유치원"
case elementary = "초등학교"
case middle = "중학교"
case high = "고등학교"
case college = "대학"
case university = "대학교"
}
let allCases: [School] = School.allCases
print(allCases)
ex) 항목 순회 - available 속성을 갖는 열거형
enum School: String, CaseIterable{
case primary = "유치원"
case elementary = "초등학교"
case middle = "중학교"
case high = "고등학교"
case college = "대학"
case university = "대학교"
@available(iOS, obsoleted: 12.0)
case graduate = "대학원"
static var allCases: [School]{
let all: [School] = [.primary, .elementary, .middle, .high, .college, .university]
#if os(iOS)
return all
#else
return all + [.graduate]
#endif
}
}
let allCases: [School] = School.allCases
print(allCases)
순환 열거형은 열거형 항목의 연관 값이 열거형 자신의 값이고자 할 때 사용한다.
순환 열거형을 명시하고 싶다면 indirect 키워드를 사용한다.
특정 항목에만 한정하고 싶다면 case 키워드 앞에 indirect을 붙이고, 열거형 전체에 적용하고 싶다면 enum앞에 indirect를 붙인다.
ex) 특정 항목의 순환 열거형 명시
enum ArithmeticExpression{
case Number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiple(ArithmeticExpression, ArithmeticExpression)
}
ex) 열거형 전체에 순환 열거형 명시
indirect enum ArithmeticExpression{
case Number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiple(ArithmeticExpression, ArithmeticExpression)
}
ex) 순환 열거형 응용
let five = ArithmeticExpression.Number(5)
let four = ArithmeticExpression.Number(4)
let sum = ArithmeticExpression.addition(five, four)
let final = ArithmeticExpression.multiple(sum, ArithmeticExpression.Number(2))
func evaluate(_ expression: ArithmeticExpression) -> Int{
switch expression{
case .Number(let value): return value
case .addition(let left, let right): return evaluate(left) + evaluate(right)
case .multiple(let left, let right): return evaluate(left) * evaluate(right)
}
}
let result: Int = evaluate(final)
print(result)
Comparable 프로토콜을 준수하는 연관 값만 갖거나 연관 값이 없는 열거형은 Comparable 프로토콜을 채택하면 각 케이스를 비교할 수 있다. 앞에 위치한 케이스가 더 작은 값이 된다.
ex) 비교 가능한 열거형
enum Condition: Comparable{
case terrible
case bad
case good
case great
}
let myCondition: Condition = Condition.great
let yourCondotion: Condition = Condition.bad
if myCondition >= yourCondotion{
print("my condition is better than you")
}else{
print("your condition is better than me")
}
enum Device: Comparable{
case iPhone(version: String)
case iPad(version: String)
case macBook
case iMac
}
var devices: [Device] = []
devices.append(Device.iMac)
devices.append(Device.iPhone(version: "14.5"))
devices.append(Device.iPhone(version: "6.1"))
devices.append(Device.iPad(version: "10.2"))
devices.append(Device.macBook)
let sortedDevices: [Device] = devices.sorted()
print(sortedDevices)