본문 바로가기
iOS/Swift

[iOS/Swift] 알아두면 유용한, 열거형(Enumeration) ②

by iosdevlime 2022. 11. 7.

Enum, 열거형에 대해 앞선 포스팅에서 언급한대로 한줄로 정리하자면..

 

연관있는 값들을 열거함으로서
사용자로 하여금 해당 값에 대해 접근하기 쉽도록 도와주는 자료형

 

 

 

다시 말해, Enum은 하나의 자료형을 사용자가 새롭게 만드는 것이고,

그 내부에는 case란 키워드와 함께 특정 명칭을 나열하는 것으로 완성된다고 이해할 수 있습니다.

 

 

 

여기서 잠깐!

case 키워드 뒤에 작성된 명칭은 정확히 얘기하자면 초기값이 없는, 말 그대로 명칭에 불과합니다.

 

 

앞서 포스팅에서 살펴본 코드를 하나 긁어오자면..

enum Color {
    case red
    case green
    case blue
}

여기서 red, green, blue가 만약 String 데이터 타입이었다면,

큰 따옴표 (" ")로 묶어서 작성했을텐데 말입니다?!

 

 

결국, 위 예시는

case 명칭의 초기값, 즉 '원시값(Raw Value)이 없는 열거형(enum)' 이라 볼 수 있습니다.

(반대로, 원시값이 할당된 경우도 존재합니다)

 

이번 포스팅에서는 enum의 원시값(Raw Value)에 대해 살펴보고,

추가적인 기능인 연관값(Associated Value) 또한 알아보도록 하겠습니다.

 

 


 

 

 

enum의 원시값(Raw Value)

Case 별 원시(초기)값을 설정, 열거형의 값의 집합 완성 

 

enum은 사용자가 직접 각각의 case에 원시값(Raw Value)을 저장할 수 있습니다.

  • 원시값의 자료 형태는 <String>, <Character>, <Number Type> 3가지 타입으로 한정됩니다.
  • 또한, 반드시 Enum 선언 및 변수값 옆에 타입을 명기해야 합니다.

 

 

 

Number Type

  • 정수 형태인 Number Type(Int)의 자료형태입니다.
    • 만약, 사용자가 원시값을 지정해주지 않을시 case 순서에 따라 '0'부터 +1씩 증가합니다.
// 1. 월요일부터 금요일까지 열거형으로 만들고, 원시값이 없는 경우
enum Weekend : Int {
    case mon
    case tue
    case wed
    case thu
    case fri
}

// case mon을 점문법을 통해 .rawValue에 접근하게 되면
Weekend.mon.rawValue // 0이 호출됨
Weekend.wed.rawValue // 2가 호출됨

 

  • 원시값이 있는 case는 해당 값을 호출, 그렇지 않다면 직전 원시값에 +1이 부여되어 호출됩니다.
// 2. case mon에 원시값 3을 할당할 경우
enum Weekend : Int {
    case mon = 3
    case tue  // 3 + 1 = 4
    case wed  // 4 + 1 = 5
    case thu  // 5 + 1 = 6
    case fri  // 6 + 1 = 7
}

Weekend.mon.rawValue // 3가 호출됩니다.
Weekend.wed.rawValue // 5가 호출됩니다.

 

 

 

String Type

  • 문자열 형태인 String Type (String)의 자료형태입니다.
    • 사용자가 지정해 주지 않을 시, case 명칭의 값을 원시값으로 가집니다.
// String Type의 원시값을 할당하거나 그렇지 않았을 경우

enum Weekend : String {
    case mon = "Worst!"
    case tue = "bad.."
    case wed // 원시값 미 지정
    case thu = "soso.."
    case fri = "good"
}

Weekend.mon.rawValue // "Worst!"
Weekend.wed.rawValue // "Wed" (원시값이 없지만, case값을 따른다)

 

 

 

Character Type

  • 문자 형태인 Character Type (Character)의 자료형태입니다.
    • 정수, 문자열 형태와는 달리 반드시 '원시값'을 지정해야 한다!

초기값이 없을때&#44; 이렇게 마구마구 오류가 발생한다.
초기값이 없을때, 이렇게 마구마구 오류가 발생한다.

 

// 문자 타입의 enum, 모든 case에 원시값을 지정했을때.. 
enum Weekend : Character {
    case mon = "A"
    case tue = "B"
    case wed = "C"
    case thu = "D"
    case fri = "E"
}

Weekend.mon.rawValue // "A"
Weekend.wed.rawValue // "C"

 

 


 

 

enum의 연관값(Associated Values)

원시값(Raw Value)의 한계를 넘어, 튜플(Tuple)의 복합타입을 활용한 다중 값 선언

 

위에서 다룬 원시값(Raw Value)는 굳이 꼽자면 아래와 같은 한계점을 가지고 있습니다.

  • 첫 번째, case하나의 원시값만 가진다.
  • 두 번째, 모든 case동일한 원시값의 자료형태(정수형, 문자열 및 문자형)를 가진다.

 

다시 말해,

동일한 형식의 Type만 가능하다는 점,

미리 지정된 값에 한하여 추출한다는 단점이자 한계가 존재합니다.

 

이와 같은 원시값의 단점을 보완하고자.. '연관값(Associated Value)'을 활용할 수 있습니다.

 

 

 

 

연관값(Associated Value)의 형태

  • Enum 이름 뒤에 타입을 선언하는 원시값과는 달리.. 연관값은 케이스 이름 뒤에 타입을 선언합니다.
    • 즉, 튜플(Tuple) 형태로 원하는 타입을 마음대로 섞어서 설정하고,
    • 사용자가 case를 호출할 때 원하는 값을 할당할 수 있습니다.
// 연관값의 기본형태

//1. unnamed Tuple (이름이 없고 타입만 있는) 
enum Name {
    case caseName(Type)
    case caseName(Type, Type, ...)
}


//2. named Tuple (이름도 있고, 타입도 있는) 
enum Name {
    case caseName(Name1: Type)
    case caseName(Name2: Type, Name3: Type, ...)
}

 

 (왼쪽) Named Tuple 연관값을 활용 / (오른쪽) UnNamed Tuple 연관값을 활용  (왼쪽) Named Tuple 연관값을 활용 / (오른쪽) UnNamed Tuple 연관값을 활용
(왼쪽) Named Tuple 연관값을 활용 / (오른쪽) UnNamed Tuple 연관값을 활용

 

 

 

 

조건문 Switch 구문을 활용한 연관값 확인

  • Enum은 조건문인 Switch 구문과 함께 주로 활용됩니다.
  • 각 case 별로 원시값 혹은 연관값이 존재한다면, Switch 구문을 통해 조건을 확인할 수 있습니다.
    • Switch 구문은, 반드시 해당 enum의 모든 case 조건이 포함 되어야 합니다!
더보기
// MyIphoneDevice란 열거형이며, 각각의 case는 String 타입의 원시값을 할당한다.
enum MyIphoneDevice: String {
    
    case iphone = "Mini"
    case ipad = "Generation 4"
    case macbook = "M1, 2021"
}


// myIphone이란 변수에 MyIphoneDevice 열거형 내 iphone case를 할당한다.
var myIphone: MyIphoneDevice = MyIphoneDevice.iphone


// Switch 조건문을 통하여 열거형 내 모든 case를 확인, 결과를 도출한다.
switch myIphone {
    case .iphone :
        print(myIphone.rawValue)
    
    case .ipad :
        print(MyIphoneDevice.ipad.rawValue)
    
    case .macbook :
        print(MyIphoneDevice.macbook.rawValue)
}

// "Mini"

 

  • 만약 연관값(Associated Value)를 활용한 Enum과 함께 사용될 경우,
    • Switch 구문은 enum의 모든 조건을 포함하되,초기화 된 값이 없을 경우  또한 포함해야 합니다.
    • 아래 예시를 통해 살펴보겠습니다.
더보기
enum MyIphoneDevice {
    
    case iphone(Int, String)
    case ipad(age:Int, _: String)
    case macbook
}

var myIPad: MyIphoneDevice = MyIphoneDevice.ipad(age: 3, "Ipad Mini")

// 모든 case가 들어가야 하며,
// 초기값이 없는 경우 또한 반드시 포함되어야 함! 

switch myIPad {
case .iphone(_, _):
    break

// 1. 초기화 값이 있는 경우
case .ipad(age: 3, _):
    print("\(myIPad)")
    
// 2. 초기화 값이 없는 경우
case .ipad(age: _ , _):
    break
    
case .macbook:
    break

}

댓글