[Swift] 열거형(Enumeration)

728x90

Swift의 열거형에 대해 알아 보겠습니다.

열거형 (Enumeration)

열거형은 연관된 항목을을 묶어서 표현할 수 있는 타입이고,
다른 타입과는 다르게 프로그래머가 정의해준 항목 값 외에는 추가/수정이 불가능합니다.

열거형 선택 사항

  • 제한된 범위네에 선택지를 주고싶을 경우
  • 정해진 값 외는 입력받고 싶지 않을 경우
  • 예상된 입력 값이 한정되어 있을 경우
  • Ex) 학생 : 초등학생, 중학생, 고등학생, 대학생, 대학원생, 기타

기본 열거형

스위프트의 열거형은 enum이라는 키워드로 선언할 수 있습니다.
각 항목은 그 자체가 고유의 값입니다.

enum School {
  case primary		// 유치원
  case elementary	// 초등
  case middle		// 중등
  case high		// 고등
  case college		// 대학
  case university	// 대학교
  case graduate		// 대학원
}

열거형 변수의 생성 및 값 변경

// 두 코드는 똑같은 표현.
var testEnum: School = School.university
var testEnum: Schhol = .university

// 값 변경
testEnum = .graduate

원시값(Raw Value)

열거형의 각 항목은 하나의 값의 역할을 할 수 있지만 항목의 원시값도 가질 수 있다. 즉, 특정 타입으로 지정된 값을 가질 수 있다는 뜻.

특정 타입의 값을 원시값으로 가지고 싶다면 열거형 오른쪽에 타입을 명시해 주시면되고,
명시값을 사용하고싶다면 rawValue라는 프로퍼티를 사용해 가져올 수 있습니다.

enum School: String {
  case primary = "유치원"		// 유치원
  case elementary = "초등학교"	// 초등
  case middle = "중학교"		// 중등
  case high = "고등학교"		// 고등
  case college = "대학"		// 대학
  case university = "대학교"	// 대학교
  case graduate = "대학원"	// 대학원
}

let education: School = School.university
print(education.rawValue) // 대학교 라고 출력 됨

만약 일부 항목만 원시값을 주고 싶다면 일부만 값을 지정해도 됩니다.
나머지는 스위프트가 알아서 처리 해줍니다.

 

예를 들어 문자열 형식의 원시 값을 지정해 줬다면 각 항목의 이름을 그래도 원시 값으로 가지게 되고, 정수형이라면 첫 항목을 기준으로 0부터 1씩 늘어난 값을 가지게 됩니다.

enum School: String {
  case primary = "유치원"		// 유치원
  case elementary = "초등학교"	// 초등
  case middle = "중학교"		// 중등
  case high = "고등학교"		// 고등
  case college = "대학"		// 대학
  case university 
  case graduate
}

print(School.university.rawValue)	// university 출력
print(School.high.rawValue)


enum Number: Int {
  case zero
  case one
  case two
  case ten = 10
  case eleven
  case twelve
}

print(Number.zero.rawValue)		// 0
print(Number.one.rawValue)		// 1
print(Number.two.rawValue)		// 2
print(Number.ten.rawValue)		// 10
print(Number.eleven.rawValue)		// 11
print(Number.twelve.rawValue)		// 12

만약 올바르지 않은 원시값을 통해 접근하려 한다면 nil을 반환한다.

print(Numbers(rawValue: 1))		// one
print(Numbers(rawValue: 5))		// nil

연관값을 가지는 열거형

열거형 내의 항목(case)이 자신과 연관된 값을 가질 수 있고, 연관 값은 항목 옆에 소괄호를 이용하여 묶어 표현할 수 있습니다.
굳이 다른 항목이 연관 값을 가진다고 모든 항목이 연관 값을 가질 필요는 없습니다.

enum PastaTaste {
    case cream, tomato
}

enum PizzaDough {
    case cheeseCrust, thin, original
}

enum PizzaTopping {
    case pepperoni, cheese, bacon
}

enum MainDish {
    case pasta(tast: PastaTaste)
    case pizza(dough: PizzaDough, topping: PizzaTopping)
    case chicken(withSauce: Bool)
    case rice
}


var dinner: MainDish = MainDish.pasta(tast: PastaTaste.cream)
dinner = MainDish.pizza(dough: PizzaDough.thin, topping: PizzaTopping.cheese)
dinner = MainDish.chicken(withSauce: true)
dinner = MainDish.rice

순환 열거형

순환 열거형은 열거형 항목의 연관 값이 자기 자신의 값이고자 할 때 사용합니다.

순환 열거형을 명시하고 싶다면 indirect 키워드를 사용합니다.
방법은 특정 항목에만 한정하고 싶다면 case키워드 앞에 indirect를 붙여 사용하고,
열거형 전체에 적용하고 싶다면 enum 키워드 앞에 indirect를 붙여 사용합니다.

 

좀더 순환(Recursive)라는 표현으로 코드를 짜보자

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 five = ArithmeticExpression.number(5)
let two = ArithmeticExpression.number(2)

let sum = ArithmeticExpression.addition(five, two)
let mul = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))

let sumResult: Int = evaluate(sum)
let mulResult: Int = evaluate(mul)

print(sumResult)		// 7
print(mulResult)		// 14