Swift/Swift 가이드

[Swift] 공식 문서 - 중첩 타입(Nested Types)

유정주 2022. 7. 30. 12:46
반응형

새로 배운 점

  • Swift는 중첩 타입(Nested Types)를 정의할 수 있습니다. 즉, 지원하는 타입의 정의 내에서 클래스, 구조체, 열거형을 중첩할 수 있습니다.

 

Nested Types

열거형은 종종 특정 클래스나 구조체 기능을 지원하기 위해 만들어지기도 합니다.

보다 복잡한 타입의 Context 내에서 사용하기 위해서는 유틸리티 클래스 및 구조체를 정의하는 것이 편리할 수 있습니다.

이를 위해 Swift는 중첩 타입(Nested Types)를 정의할 수 있습니다.

즉, 지원하는 타입의 정의 내에서 클래스, 구조체, 열거형을 중첩할 수 있습니다.

 

타입을 다른 타입에 중첩키시려면 지원하는 타입의 외부 중괄호 안에 해당 정의를 작성하면 됩니다.

타입은 필요한만큼 중첩할 수 있습니다.

 

Nested Types in Action

아래 예제는 BlackjackCard 구조체를 정의합니다.

BlackjackCard 구조체는 Blackjack 게임에서 사용되는 카드를 모델링합니다.

BlackjackCard 구조체에는 Suit 및 Rank라는 두 개의 중첩된 열거 타입이 있습니다.

 

Blackjack에서는 Ace 카드의 값이 1 또는 11입니다.

이 기능은 Valued라는 구조체로 표현되며 Rank 열거형 내에 중첩되어 있습니다.

struct BlackjackCard {

    // nested Suit enumeration
    enum Suit: Character {
        case spades = "♠", hearts = "♡", diamonds = "♢", clubs = "♣"
    }

    // nested Rank enumeration
    enum Rank: Int {
        case two = 2, three, four, five, six, seven, eight, nine, ten
        case jack, queen, king, ace
        struct Values {
            let first: Int, second: Int?
        }
        var values: Values {
            switch self {
            case .ace:
                return Values(first: 1, second: 11)
            case .jack, .queen, .king:
                return Values(first: 10, second: nil)
            default:
                return Values(first: self.rawValue, second: nil)
            }
        }
    }

    // BlackjackCard properties and methods
    let rank: Rank, suit: Suit
    var description: String {
        var output = "suit is \(suit.rawValue),"
        output += " value is \(rank.values.first)"
        if let second = rank.values.second {
            output += " or \(second)"
        }
        return output
    }
}

Suit 열거 값은 카드에서 사용하는 4가지 모양을 표현하고, raw 값은 그 모양의 기호를 나타냅니다.

Rank 열거값은 카드에서 사용 가능한 13가지 카드 등급을 표현하고, raw 값은 그 등급의 값을 나타냅니다.

이 raw값은 Jack, Queen, King, Ace 카드에서는 사용되지 않습니다.

 

위에서 언급했던 것처럼 Rank 값은 중첩으로 Values 구조체 타입을 정의합니다.

이 구조체는 대부분의 카드는 한 개의 값만 가지지만 Ace 카드만 두 개를 갖는 특징을 캡슐화 해줍니다.

Values 구조체는 이를 위해 아래처럼 정의됩니다.

  • first : Int 타입
  • second : Int? 타입

Values 구조체는 연산 프로퍼티로 정의됩니다.

Ace, Jack, Queen, King 등 first와 second 값을 모두 갖는 카드는 그거에 맞게 값을 반환하고

first 값만 갖는 나머지 카드는 second를 nil로 반환합니다.

 

BlackjackCard 구조체는 커스텀 이니셜라이저가 없기 때문에

암시적으로 멤버와이즈 이니셜라이저를 갖습니다.

그래서 아래와 같이 rank와 suit를 인자로 받아 인스턴스를 생성합니다.

let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
print("theAceOfSpades: \(theAceOfSpades.description)")
// Prints "theAceOfSpades: suit is ♠, value is 1 or 11"

.ace, .spades가 BlackjackCard 구조체 안에서 중첩 타입으로 선언돼 있기 때문에 타입 추론이 가능합니다.

그래서 인자로 넘긴 rank와 suit는 타입형의 전체를 명시하지 않아도 .ace, .spades로 사용할 수 있습니다.

 

Referring to Nested Types

정의 context 외부에서 중첩 타입을 사용하려면 해당 이름 앞에 nested type의 이름을 붙이면 됩니다.

let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
// heartsSymbol is "♡"

 

 

참고

https://docs.swift.org/swift-book/LanguageGuide/NestedTypes.html

 

 

반응형