[Swift 공식문서 읽기]Enumerations

llim🧚🏻‍♀️·2021년 8월 12일
1

Swift

목록 보기
8/26
post-thumbnail

안녕하세요. 엘림입니다🙇🏻‍♀️

Swift 공식 문서 정독하기 8편입니다!

제 스타일대로 정리했으니 추가적으로 더 필요한 정보는
공식문서 링크를 눌러 확인해주세용!

좀 더 편하게 보기위해 한국어로 번역된 사이트를 함께 확인했습니다!ㅎㅎ

자, 그럼 시작해볼까요

이 글은 공부하면서 작성한 글이기 때문에 잘못된 정보가 있을 수 있습니다.🥺
금방 잊어버릴... 미래의 저에게 다시 알려주기 위한 글이다보니
혹시라도 틀린 부분이 있다면, 댓글로 친절하게 알려주시길 부탁드립니다.🙏


열거형

열거형은 관련된 값으로 이루어진 그룹을 하나의 타입으로 선언해 안전성(type-safety)을 보장하는 방법입니다. 스위프트에서는 case값으로 string, character, integer, floting 등 을 사용할 수 있습니다. 열거형은 1급 클래스 형(first-class types)이어서 연산 프로퍼티(computed properties)를 제공하거나 초기화를 지정하거나, 초기 선언을 확장해 사용할 수 있습니다.

문법

enum CompassPoint {
    case north
    case south
    case east
    case west
}

enum Planet {
    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}

Swift에서 열거형은 생성될 때 각 case 별로 기본 integer값을 할당하지 않습니다

var directionToHead = CompassPoint.west
directionToHead = .east

directionToHead의 형은 초기화 될 때 타입추론이 돼서 CompassPoint형을 갖게 됩니다. directionToHead의 형이 CompassPoint로 한번 정의되면 다음에 값을 할당할 때 형을 생략한 점 문법(dot syntax)을 이용해 값을 할당하는 축약형 문법을 사용할 수 있습니다.

Switch 구문과 사용하기

directionToHead = .south
switch directionToHead {
case .north:
    print("Lots of planets have a north")
case .south:
    print("Watch out for penguins")
case .east:
    print("Where the sun rises")
case .west:
    print("Where the skies are blue")
}
// Prints "Watch out for penguins"

let somePlanet = Planet.earth
switch somePlanet {
case .earth:
    print("Mostly harmless")
default:
    print("Not a safe place for humans")
}

switch문은 반드시 열거형의 모든 경우(cases)를 완전히 포함해야 합니다. 만약 case가 생략되었다면 코드는 컴파일 되지 않습니다. 만약 열거형의 모든 cases의 처리를 기술하는게 적당하지 않다면 기본(default) case를 제공함으로써 처리되지 않는 case를 피할 수 있습니다.

For-In 구문과 사용하기

enum Beverage: CaseIterable {
    case coffee, tea, juice
}
let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available")
// Prints "3 beverages available"

for beverage in Beverage.allCases {
    print(beverage)
}
// coffee
// tea
// juice

CaseIterable을 채택한 enum은 allCases을 다른 컬렉션처럼 사용할 수 있습니다.

💡 CaseIterable 공식 문서 링크

관련 값

열거형의 각 case에 custom type의 추가적인 정보를 저장할 수 있습니다.

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")

예를 들어 바코드가 위와 같이 4가지 구분으로 이루어진 숫자로 이루어진 종류가 있거나, 2,953개의 문자로 구성된 QR코드 형태로 이루어진 두 가지 종류가 있다면 이 바코드를 아래와 같은 열거형으로 정의할 수 있습니다.

switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
    print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
    print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."

switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
    print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
    print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."

case 안의 관련 값이 전부 상수이거나 변수이면 공통된 값을 case 뒤에 선언해서 보다 간결하게 기술할 수 있습니다. 공통된 let을 앞으로 빼내 간결하게 기술도 가능합니다.

Raw Values

enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}

각 raw값은 열거형 선언에서 유일한 값으로 중복되어서는 안됩니다.

암시적으로 할당된 Raw 값

열거형을 다루면서 raw값으로 Integer나 String 값을 사용할 수 있는데, 각 case별로 명시적으로 raw값을 할당할 필요는 없습니다. 만약 raw값을 할당하지 않으면 Swift에서 자동으로 값을 할당해 줍니다.

enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

enum CompassPoint: String {
    case north, south, east, west
}

let earthsOrder = Planet.earth.rawValue
// earthsOrder is 3

let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection is "west"

mercury에 1을 raw 값으로 명시적으로 할당했고 venus는 암시적으로 2 그리고 이후 값은 1증가 된 값을 자동으로 raw값으로 갖게 됩니다. 만약 String을 raw값으로 사용한다면 case텍스트가 raw값으로 자동으로 raw값으로 할당됩니다.
또한, CompassPoint.south는 암시적으로 "south"를 raw값으로 갖습니다.

Raw 값을 이용한 초기화

let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet is of type Planet? and equals Planet.uranus

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)")
}
// Prints "There isn't a planet at position 11"

raw 값 초기자는 모든 raw값에 대해 열거형 case를 반환이 보장되지 않으므로 실패할 수 있는 초기자(failable initializer)입니다.
만약 열거형에 지정된 raw값이 없는 값으로 초기자를 지정하면 그 값은 nil이 됩니다.

재귀 열거

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)
}

재귀 열거자는 다른 열거 인스턴스를 관계 값으로 갖는 열거형입니다. 재귀 열거자 case는 앞에 indirect키워드를 붙여 표시합니다.
만약 관계 값을 갖는 모든 열거형 case에 indirect표시를 하고 싶으면 enum키워드 앞에 indirect표시를 하면 됩니다.

let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))

func evaluate(_ expression: ArithmeticExpression) -> Int {
    switch expression {
    case let .number(value):
        return value
    case let .addition(left, right):
        return evaluate(left) + evaluate(right)
    case let .multiplication(left, right):
        return evaluate(left) * evaluate(right)
    }
}

print(evaluate(product))
// Prints "18"

오늘은 스위프트 공식문서에서 Enumerations 읽어보았습니다~
다음에는 Structures and Classes를 읽어보도록 하겠습니다!

감사합니다🙇🏻‍♀️

profile
한달 차 iOS 개발자입니다🐥

0개의 댓글