Swift - 20. 중첩 타입 Nested Types

지우개·2022년 4월 7일
0

Swift study

목록 보기
9/15
post-thumbnail

열거형은 특정 구조체나 클래스의 기능을 처리하기 위해 자주 사용된다. 이와 비슷하게 특정 문맥에서 좀 더 복잡한 타입을 위해 사용할 수 있는 유틸리티 클래스나 구조체를 정의할 수 있다.
Swift에서는 이 기능을 위해 중첩 타입을 지원한다. 열거형, 클래스, 구조체를 그 타입 안에서 다시 정의할 수 있다.

중첩 타입의 사용 Nested Types in Action

예제 블랙잭 게임
블랙잭 게임에서 사용되는 게임 카드를 모델링하는 BlackjackCard 구조체 - SuitRank라는 2개의 중첩된 열거형 포함
블랙잭에서 에이스 카드의 값은 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가지 모양을 나타낸다. raw 값은 그 모양의 기호를 나타낸다.
Rank 열거형은 13개의 카드 순위를 나타낸다. raw 값은 그 등급의 값을 나타낸다. (J, Q, K, A 카드에서는 사용되지 않음)

Rank 값은 그 값 자체의 중첩 구조체인 Values라는 값을 정의한다. 이 구조는 대부분의 카드가 하나의 값만 가지지만 Ace 카드는 두 개를 갖는데 이것을 캡슐화 해준다.
Values 구조체는 이것을 표현하기 위해

  • first : Int 타입
  • second : Int?
    를 정의한다.

Rank는 또 계산된 프로퍼티를 정의해 사용한다.
Ace, Jack, Queen, King 등 first, second 값을 모두 갖는 카드는 그에 맞게 값을 반환하고 나머지 보통 숫자에 대해서는 first 값만 존재하고 second 값은 nil인 값을 반환한다.

BlackjackCardranksuit 두 개의 프로퍼티를 소유하고 description이라고 부르는 계산된 프로퍼티도 정의한다. BlackjackCard는 커스텀 초기자가 없는 구조체이기 때문에 암시적인 멤버와이즈 초기자(implicit memberwise initializer)를 갖는다. 그래서 아래 코드와 같이 ranksuit를 인자로 받아 BlackjackCard를 초기화할 수 있다.

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

중첩 타입의 언급 Referring to Nested Types

중첩 타입을 선언 밖에서 사용하려면 선언된 곳의 시작부터 끝까지 적어주어야 한다.

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

참고
https://jusung.gitbook.io/the-swift-language-guide/language-guide/19-nested-types
https://bbiguduk.gitbook.io/swift/language-guide-1/nested-types

0개의 댓글