ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Swift 정리 #8 Enumerations
    코딩/Swift 2022. 12. 28. 22:44
    728x90

    Enumerations 열거형

    Syntax

    // enum keyword
    enum CompassPoint {
        // enumeration type은 복수형보다는 단수형을 사용
        case north
        case south
        case east
        case west
    }
    
    // directionToHead가 CompassPoint로 한 번 선언된 후,
    // . 을 사용한 다른 CompassPoint 값으로 지정.
    var directionToHead = CompassPoint.west
    directionToHead = .east
    enum Planet {
        case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
        // Multiple cases on a single line
    }

    Switch문으로 enumeration 매칭

    // switch statement
    directionToHead = .south
    switch directionToHead {
        // switch문은 enumeration의 case들을 고려할 때
        // 요소들을 꼭 채워야 한다.
    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"
    // 모든 case에 값을 넣을 필요 없는 경우,
    // 값이 없는 요소를 위해 default:를 지정.
    let somePlanet = Planet.earth
    switch somePlanet {
    case .earth:
        print("Mostly harmless")
    default:
        print("Not a safe place for humans")
    }
    // Prints "Mostly harmless"

    Enumeration case의 반복

    // 모든 케이스를 컬렉션으로 지정
    // : CaseIterable
    // .allCases
    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

    Associated Values

    // associated values
    // 케이스 값과 함께 다른 유형의 값을 저장
    enum Barcode {
        case upc(Int, Int, Int, Int)
        // type (Int, Int, Int, Int) associated value의 upc 지정
        case qrCode(String)
        // type String associated value의 qrCode 지정
    }
    
    var productBarcode = Barcode.upc(8, 85909, 51226, 3)
    productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
    
    // 각 associated value를 상수(let 접두사 포함) 또는 변수(var 접두사 포함)로 추출
    // 스위치 케이스의 본문 내에서 사용
    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."
    
    // 위와 동일한 표현
    // 간결성 위해 let을 case 이름 앞에 let 추가
    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."

    Raw Values

    // 기본값(raw value), 모두 같은 타입
    // raw value는 enumeration 정의할 때 설정. 항상 동일.
    // associated value는 상수나 변수 만들 때 설정. 변경됨.
    enum ASCIIControlCharacter: Character { // Character 타입
        case tab = "\t"
        case lineFeed = "\n"
        case carriageReturn = "\r"
    }

    암시적으로 할당된 Raw Value

    // raw value가 integer 또는 string일 때,
    // 명시적으로 값을 지정할 필요 없음.
    // integer일 경우, 첫번째 값은 0(암시적)
    enum Planet: Int {
        case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
        // mercury의 raw value=1, 다음부터 2,3...
    }
    enum CompassPoint: String {
        // string은 case 이름을 암시적 raw value로 설정
        case north, south, east, west
    }
    
    // .rawValue property
    let earthsOrder = Planet.earth.rawValue
    // earthsOrder is 3
    
    let sunsetDirection = CompassPoint.west.rawValue
    // sunsetDirection is "west"

    Raw Value에서의 초기화

    // Raw value 유형으로 Enumeration을 정의하는 경우, 이니셜라이저 자동 수신
    let possiblePlanet = Planet(rawValue: 7)
    // 이니셜라이저로 enumeration의 새 인스턴스 생성
    // 이니셜라이저: rawValue를 매개변수로 raw value type의 값을 사용, enumeration case 또는 nil을 반환
    // possiblePlanet is of type Planet? and equals Planet.uranus
    
    // optional binding
    // 바인딩되는 값이 없을 경우 optional enumeration case
    // 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)")
    }
    // Prints "There isn't a planet at position 11"

    Recursive Enumerations; 재귀적 enumeration

    // 재귀적 enumeration은 associated value enumeration의 하나 또는 이상의 enumeration case들을 위한
    // 또 다른 인스턴스.
    enum ArithmeticExpression {
        case number(Int)
        //`indirect case`로 컴파일러는 필요한 재귀층을 삽입.
        indirect case addition(ArithmeticExpression, ArithmeticExpression)
        indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
    }
    // indirect를 enum 앞에 표기: 모든 케이스가 enum
    indirect enum ArithmeticExpression {
        case number(Int)
        case addition(ArithmeticExpression, ArithmeticExpression)
        case multiplication(ArithmeticExpression, ArithmeticExpression)
    }

    재귀적 용법의 설명
    예의 enumeration은 일반 숫자, 두 식의 더하기 및 두 식의 곱의 세 가지 산술 식을 저장.
    덧셈과 곱셈의 경우에는 산술 표현식이기도 한 associated value가 있다.
    이러한 associated value를 사용하면 식을 중첩할 수 있다.
    예를 들어, 식 (5 + 4) * 2는 곱셈의 오른쪽에 숫자가 있고 곱셈의 왼쪽에 또 다른 식이 있다.
    데이터가 중첩되어 있기 때문에 데이터를 저장하는 데 사용되는 enumeration도 중첩을 지원해야 합다.
    즉, enumeration이 재귀적이어야 한다.

    // (5 + 4) * 2에 대해 생성되는 ArithmeticExpression 재귀 열거
    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"

    This function evaluates a plain number by simply returning the associated value. It evaluates an addition or multiplication by evaluating the expression on the left-hand side, evaluating the expression on the right-hand side, and then adding them or multiplying them.

    이 함수는 단순히 관련 값을 반환하여 일반 숫자를 계산.
    왼쪽 식을 평가하고 오른쪽 식을 평가한 다음 더하거나 곱하여 덧셈이나 곱셈을 계산.

    728x90

    '코딩 > Swift' 카테고리의 다른 글

    Swift/Tour  (0) 2024.03.02
    Swift 정리 #9 구조체와 클래스  (0) 2022.12.28
    Swift 정리 #7 클로저  (1) 2022.12.14
    Swift 정리 #6 함수  (0) 2022.12.14
    Swift 정리 #5 Control flow  (1) 2022.12.14

    댓글

Designed by Tistory.