연관 값을 같는 열거형
enum MainDish {
case pasta(taste: String)
case pizza(dough: String, topping: String)
case chicken(withSource: Bool)
case rice
}
var dinner: MainDish = MainDish.pasta(taste: "크림")
print(dinner)
dinner = .pizza(dough: "치즈크러스트", topping: "불고기")
print(dinner)
dinner = .chicken(withSource: true)
print(dinner)
dinner = .rice
print(dinner)
// pasta(taste: "크림")
// pizza(dough: "치즈크러스트", topping: "불고기")
// chicken(withSource: true)
// rice
여러 열거형의 응용
enum PastaTaste{
case cream, tomato
}
enum PizzaDough{
case cheeseCrust, thin, original
}
enum PizzaTopping{
case pepperoni, cheese, bacon
}
enum MainDish{
case pasta(taste: PastaTaste)
case pizza(dough: PizzaDough, topping: PizzaTopping)
case chicken(withSource: Bool)
case rice
}
var dinner: MainDish = MainDish.pasta(taste: PastaTaste.tomato)
print(dinner)
dinner = MainDish.pizza(dough: PizzaDough.cheeseCrust, topping: PizzaTopping.bacon)
print(dinner)
// pasta(taste: __lldb_expr_17.PastaTaste.tomato)
// pizza(dough: __lldb_expr_17.PizzaDough.cheeseCrust, topping: __lldb_expr_17.PizzaTopping.bacon)
CaseIterable 프로토콜을 활용한 열거형의 항목 순회
avaliable 속성을 갖는 열거형의 항목 순회 (allCases 프로퍼티 사용)
enum School: String, CaseIterable {
case primary = "유치원"
case elementary = "초등학교"
case middle = "중학교"
case high = "고등학교"
case college = "대학"
case universary = "대학교"
@available(iOS, obsoleted: 12.0)
case graduate = "대학원"
static var allCases: [School] {
let all: [School] = [.primary,
.elementary,
.middle,
.high,
.college,
.universary]
#if os(iOS)
return all
#else
return all + [.graduate]
#endif
}
}
let allCases: [School] = School.allCases
print(allCases)
// 실행 환경에 따라 다른 결과
// 일단 내 환경에서는
// [__lldb_expr_19.School.primary, __lldb_expr_19.School.elementary, __lldb_expr_19.School.middle, __lldb_expr_19.School.high, __lldb_expr_19.School.college, __lldb_expr_19.School.universary]
특정 속성을 통해 특정 케이스를 플랫폼에 따라 사용할 수 있거나 없는 경우가 생기면 CaseIterable 프로토콜을 채택하는 것 만으로는 allCases 프로퍼티를 사용할 수 없다.
그럴때는 직접 allCases 프로퍼티를 구현해 주어야 한다.
연관 값을 같는 열거형의 항목 순회 (CaseIterable 프로토콜을 채택하여도 allCases 프로퍼티를 바로 사용할 수 없는 경우)
enum PastaTaste: CaseIterable {
case cream, tomato
}
enum PizzaDough: CaseIterable {
case cheeseCrust, thin, original
}
enum PizzaTopping: CaseIterable {
case pepperoni, cheese, bacon
}
enum MainDish: CaseIterable{
case pasta(taste: PastaTaste)
case pizza(dough: PizzaDough, topping: PizzaTopping)
case chicken(withSource: Bool)
case rice
static var allCases: [MainDish] {
return PastaTaste.allCases.map(MainDish.pasta) + PizzaDough.allCases.reduce([]) { (result, dough) -> [MainDish] in result + PizzaTopping.allCases.map{(topping) -> MainDish in MainDish.pizza(dough: dough, topping: topping)}}
+ [true, false].map(MainDish.chicken)
+ [MainDish.rice]
}
}
print(MainDish.allCases.count) // 14
print(MainDish.allCases) // 모든 경우의 연관 값을 갖는 케이스 컬렉션
14
[__lldb_expr_21.MainDish.pasta(taste: __lldb_expr_21.PastaTaste.cream), __lldb_expr_21.MainDish.pasta(taste: __lldb_expr_21.PastaTaste.tomato), __lldb_expr_21.MainDish.pizza(dough: __lldb_expr_21.PizzaDough.cheeseCrust, topping: __lldb_expr_21.PizzaTopping.pepperoni), __lldb_expr_21.MainDish.pizza(dough: __lldb_expr_21.PizzaDough.cheeseCrust, topping: __lldb_expr_21.PizzaTopping.cheese), __lldb_expr_21.MainDish.pizza(dough: __lldb_expr_21.PizzaDough.cheeseCrust, topping: __lldb_expr_21.PizzaTopping.bacon), __lldb_expr_21.MainDish.pizza(dough: __lldb_expr_21.PizzaDough.thin, topping: __lldb_expr_21.PizzaTopping.pepperoni), __lldb_expr_21.MainDish.pizza(dough: __lldb_expr_21.PizzaDough.thin, topping: __lldb_expr_21.PizzaTopping.cheese), __lldb_expr_21.MainDish.pizza(dough: __lldb_expr_21.PizzaDough.thin, topping: __lldb_expr_21.PizzaTopping.bacon), __lldb_expr_21.MainDish.pizza(dough: __lldb_expr_21.PizzaDough.original, topping: __lldb_expr_21.PizzaTopping.pepperoni), __lldb_expr_21.MainDish.pizza(dough: __lldb_expr_21.PizzaDough.original, topping: __lldb_expr_21.PizzaTopping.cheese), __lldb_expr_21.MainDish.pizza(dough: __lldb_expr_21.PizzaDough.original, topping: __lldb_expr_21.PizzaTopping.bacon), __lldb_expr_21.MainDish.chicken(withSource: true), __lldb_expr_21.MainDish.chicken(withSource: false), __lldb_expr_21.MainDish.rice]
순환 열거형
열거 형 항목의 연관 값이 열거형 자신의 값이고자 할 때 사용
특정 항목에만 한정하고 싶다면 case 키워드 앞에 indirect를 붙이면 되고, 열거형 전체에 적용하고 싶다면 enum 키워드 앞에 indirect 키워드를 붙이면 된다.
// 특정 항목에만 순환 열거형 항목 표시
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
// 열거형 전체에 순환 열거형 명시
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
➰ ArithmeticExpression 열거형을 사용하여 (5 + 4) x 2 연산 구현해보기
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let final = ArithmeticExpression.multiplication(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 .multiplication(let left, let right):
return evaluate(left) * evaluate(right)
}
}
let result: Int = evaluate(final)
print("(5+4) x 2 = \(result)") //(5+4) x 2 = 18
Reference
Swift : 스위프트 프로그래밍 - 야곰
'Swift' 카테고리의 다른 글
[Swift] 함수 : 입출력 매개변수 활용, 데이터 타입으로써의 함수, 중첩 함수, @discardableResult (0) | 2022.03.16 |
---|---|
[Swift] 사용자 정의 연산자 : 전위, 중위, 후위 연산자 (0) | 2022.03.15 |
[Swift] 컬렉션형 : 배열, 딕셔너리, 세트 (0) | 2022.03.15 |
[Swift] CustomStringConvertible > description (0) | 2022.03.14 |
[Swift] 스위프트의 함수형 프로그래밍 패러다임 (0) | 2022.03.14 |