🔥 원시값

578자
7분

연관값에서 살펴본 바코드 예제는 열거형의 case가 서로 다른 타입의 연관 값을 저장할 수 있다는 것을 보여주었습니다. 연관 값의 대안으로, 열거형 case는 모두 같은 타입인 기본 값(raw values라고 함)으로 미리 채워질 수 있답니다.

다음은 ASCII 값을 이름이 있는 열거형 case와 함께 저장하는 예시랍니다:

enum ASCIIControlCharacter: Character {
    case tab = "\\t"       // 탭 문자를 나타내는 case
    case lineFeed = "\n"  // 개행 문자를 나타내는 case
    case carriageReturn = "\\r"  // 캐리지 리턴 문자를 나타내는 case
}
swift

여기서 ASCIIControlCharacter라는 열거형의 원시 값은 Character 타입으로 정의되었고, 일반적인 ASCII 제어 문자 중 일부로 설정되었어요. Character 값은 Strings and Characters에서 설명하고 있지요.

원시 값은 문자열, 문자, 또는 정수나 부동 소수점 숫자 타입 중 하나가 될 수 있습니다. 각 원시 값은 열거형 선언 내에서 고유해야 해요.

암시적으로 할당된 원시 값

정수나 문자열 원시 값을 저장하는 열거형으로 작업할 때, 각 case에 명시적으로 원시 값을 할당할 필요는 없답니다. 할당하지 않으면 Swift가 자동으로 값을 할당해 준답니다.

예를 들어, 정수가 원시 값으로 사용되면 각 case의 암시적 값은 이전 case보다 1 더 큰 값이에요. 첫 번째 case에 값이 설정되지 않았다면 그 값은 0이 됩니다.

아래 열거형은 이전의 Planet 열거형을 개선한 것으로, 태양으로부터 각 행성의 순서를 나타내는 정수 원시 값을 가지고 있네요:

enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
    // mercury는 명시적으로 1로 설정되었고, 나머지는 자동으로 2, 3, 4... 값이 할당됨
}
swift

위의 예시에서 Planet.mercury는 명시적 원시 값 1을 가지고, Planet.venus는 암시적 원시 값 2를 가지는 식이에요.

문자열이 원시 값으로 사용되면 각 case의 암시적 값은 해당 case 이름의 텍스트가 된답니다.

아래 열거형은 이전의 CompassPoint 열거형을 개선한 것으로, 각 방향의 이름을 나타내는 문자열 원시 값을 가지고 있어요:

enum CompassPoint: String {
    case north, south, east, west
    // north는 "north", south는 "south"... 문자열 값이 자동 할당됨
}
swift

위의 예시에서 CompassPoint.south는 암시적 원시 값 "south"를 가지고 있죠.

열거형 case의 원시 값은 rawValue 속성으로 접근할 수 있습니다:

let earthsOrder = Planet.earth.rawValue
// earthsOrder는 3
 
let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection은 "west"
swift

원시 값에서 초기화하기 (Initializing from a Raw Value)

열거형을 원시 값 타입으로 정의하면, 열거형은 자동으로 원시 값 타입의 값을 받아 (rawValue라는 매개변수로) 열거형 case 또는 nil을 반환하는 이니셜라이저를 받게 됩니다. 이 이니셜라이저를 사용하여 열거형의 새 인스턴스를 만들 수 있어요.

다음 예제는 원시 값 7로 Uranus를 식별합니다:

let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet은 Planet? 타입이고 Planet.uranus와 같음
swift

그러나 모든 가능한 Int 값이 일치하는 행성을 찾는 것은 아니에요. 이 때문에 원시 값 이니셜라이저는 항상 optional 열거형 case를 반환합니다. 위의 예시에서 possiblePlanetPlanet? 타입, 즉 "옵셔널 Planet" 이에요.

11의 위치로 행성을 찾으려고 하면, 원시 값 이니셜라이저가 반환하는 옵셔널 Planet 값은 nil이 될 거예요:

let positionToFind = 11
if let somePlanet = Planet(rawValue: positionToFind) {
    switch somePlanet {
    case .earth:
        print("Mostly harmless")
    default:
        print("Not a safe place for humans")
    }
} else {
    print("There isn't a planet at position \(positionToFind)")
}
// "There isn't a planet at position 11" 출력
swift

이 예제는 옵셔널 바인딩을 사용하여 원시 값 11로 행성에 접근하려고 합니다. if let somePlanet = Planet(rawValue: 11) 문은 옵셔널 Planet을 생성하고, 그 옵셔널 Planet을 검색할 수 있다면 somePlanet을 해당 값으로 설정합니다. 이 경우에는 위치 11에 해당하는 행성을 검색할 수 없기 때문에 else 분기가 대신 실행되는 거죠.

$ swift enumRawValue.swift
There isn't a planet at position 11
shell

이렇게 Swift의 열거형은 연관 값뿐만 아니라 원시 값도 지원하여 다양하고 유연한 활용이 가능하답니다. 특히 정수나 문자열 원시 값을 사용하면 각 case에 암시적으로 자동 할당되는 편리함도 있지요. 원시 값을 통해 열거형의 case를 생성하거나 switch 문에서 활용하는 등 열거형을 보다 강력하게 사용할 수 있게 되는 거예요!