[Swift] Nested Types

상 원·2022년 7월 26일
0

Swift

목록 보기
28/31
post-thumbnail

열거형은 보통 클래스나 구조체의 기능을 지원해주기 위해서 쓰이는 경우가 많다.
구조체와 클래스도 더 복잡한 타입 안에서 쓰이기 위해서 정의될 수 있음!

이걸 위해서 Swift는 nested types 라는 걸 정의해 주는데, 열거형, 클래스, 구조체를 얘네가 지원하는 또다른 타입 안에서 정의할 수 있도록 해 주는거임!

nest 하기 위해서는 그냥 지원받는 타입 중괄호 안에다가 정의해 주면 됨. 간단하쥬?

Nested Types in Action

요건 블랙잭이라는 게임에서 쓰는 카드에 관한 구조체임! 어떤 카드가 얼마의 값을 갖고 있는지 알려줄 수 있다.
Suit, Rank 라는 두 개의 열거형을 nest하고 있당.

블랙잭에서 에이스 카드는 1이나 11의 값을 갖고 있음. 이걸 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 열거형은 카드 종류(모양)을 나타낸다. 각 모양별로 raw value를 넣어놓음.

Rank 열거형은 13개의 카드 랭크(순서)를 나타내는데, 2~10까지의 숫자를 raw value로 갖고 있고, jack, queen, king, ace는 아래의 values 계산 프로퍼티에서 새로운 Values 구조체 인스턴스를 반환함.
이때 에이스면 1과 11 두 개의 값을 반환하고, 나머지 숫자들은 값을 하나씩 가지므로 하나씩만 넣어서 Values 인스턴스를 만듦.

description 계산 프로퍼티에서 output 에다가 현재 카드의 suit와 값을 문장으로 만들어서 반환하는데, second 값이 있다면 이거까지 추가해서 반환된다.

그래서 이걸 실행해보면~

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

요런식으로 나옴. 커스텀 이니셜라이저가 없기 때문에 기본으로 생성되는 memberwise 이니셜라이저를 사용한다.

Referring to Nested Types

이 nested type을 밖에서 접근해보자.
젤 바깥 구조체나 클래스부터 불러줘야 함.

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

요런식으로!

profile
ios developer

0개의 댓글