Nested Types

Swift/Language Guide 2018. 9. 18. 00:04
반응형

[최종 수정일 : 2018.09.05]

원문 : 애플 개발 문서 Swift 4.2 Language Guide - Nested Types

중첩된 타입(Nested Types)

열거형은 종종 특정 클래스나 구조체 기능을 지원하기 위해 생성됩니다. 유사하게, 유틸리티 클래스와 보다 복잡한 타입의 컨텍스트에서 사용하기 위한 순수한 구조체를 정의하는 것이 편리할 수 있습니다. 이를 위해서(to accomplish this), Swift는 중첩된 타입(nested types) 정의가 가능하며, 이를 지원하는 열거형, 클래스, 구조체를 타입의 정의에서 중첩을 할 수 있습니다.

다른 타입에서 타입을 중첩하려면, 지원하는 타입의 바깥쪽 중괄호(})안에 정의를 작성합니다. 타입은 필요한 만큼 여러 단계로 중첩될 수 있습니다.

중첩된 타입 동작(Nested Types in Action)

아래 예제는 블랙잭(Blackjack) 게임에 사용되는 카드 놀이를 모델링하는 구조체BlackjackCard를 정의합니다. BlackjackCard 구조체는 2개의 중첩된 열거형 타입. Suit와 Rank를 포함합니다.

블랙잭에서, Ace 카드는 1 또는 11 값입니다. 이 기능은 Rank열거형으로 중첩된 Values 구조체에 의해서 표현됩니다.

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벌(suits)을 심볼(symbol)을 표현하기 위한 원시(raw) Character값과 함께 설명합니다.

Rank 열거형은 13개의 게임 가능한 카드 순위를 액면 값을 표현하기 위해 원시(row) Int 값과 함께설명합니다. (Int 원시(row) 값은 Jack, Queen, King, Ace카드에는 사용되지 않습니다)

위에서 언급했던 것처럼, Rank열거형은 자체적으로 더 중첩시킨 구조체. Values를 정의합니다. 이 구조체는 대부분의 카드가 하나의 값을 가지고 있다는 것을 캡슐화 하지만, Ace 카드는 2개의 값을 가집니다. Values 구조체는 다음을 표현하기 위해 2개의 프로퍼리를 정의합니다.

  • Int타입의 first
  • Int?타입 또는 옵셔널 Int인 second

또한, Rank는 Values 구조체의 인스턴스를 반환하는 계산 프로퍼티 values를 정의합니다. 이 계산 프로퍼티는 카드의 순위와 새로운 Values 인스턴스를 순위를 기반으로 적절한 값으로 초기화 합니다. jack, queen, king, ace에 대해서 특별한 값을 사용합니다. 숫자 카드들에 대해서는, 순위(rank)의 Int 원시(raw) 값을 사용합니다.

BlackjackCard 구조체는 자체적으로 2개의 프로퍼티(rank와 suit)를 가집니다. 또한, 카드의 이름과 값을 설명하하기 위해 rank와 suit 에서 저장된 값을 사용하는 계산 프로퍼티 description을 정의 합니다. description 프로퍼티는 두번째 값을 보여주는지 검사하기 위해 옵셔널 바인딩을 사용하고, 만약 있다면, 두번째 값에 대한 자세한 추가 설명을 삽입합니다.

BlackjackCard가 사용자정의 초기화가 없는 구조체이기 때문에, . 구조체 타입에 대한 멤버단위 초기화(Memberwise Initializers for Structure Types)에서 설명된 것 처럼, 암시적인 멤버별(memberwise) 초기화를 가지고 있습니다 새로운 상수 theAceOfSpades를 초기화 하기 위해 이 초기화를 사용할 수 있습니다.

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

Rank와 Suit가 BlackjackCard 안에 중첩되어 있더라도, 이러한 타입은 컨텍스트(context)에 의해 추론될 수 있고, 이 인스턴스의 초기화는 열거형 이름(.ace, .spades) 단독으로 열거형 케이스(case)를 참조 할 수 있습니다. 위 예제에서, description프로퍼티는 스페이드(Spades)에이스(Ace)가 1 또는 11의 값을 가지고 있는 것을 정확하게 기록합니다.

중첩된 타입을 참조하기(Referring to Nested Types)

정의된 컨텍스트(context)의 바깥쪽에서 중첩된 타입을 사용하기 위해, 이름 앞에 중첩된 타입의 이름을 접두사(prefix)로 붙입니다.

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

위 예제의 경우에, 이러한 이름들을 정의된 컨텍스트에 의해, 자연스럽게 어울리기 때문에, SuitRankValues의 이름을은, 의도적으로 짧게 유지하는게 가능합니다.

반응형

'Swift > Language Guide' 카테고리의 다른 글

Automatic Reference Counting  (0) 2018.09.18
Generics  (0) 2018.09.18
Protocols  (0) 2018.09.18
Extensions  (0) 2018.09.18
Type Casting  (0) 2018.09.18
Error Handling  (0) 2018.09.18
Optional Chaining  (0) 2018.09.18
Deinitialization  (0) 2018.09.18
Posted by 까칠코더
,