Nested Types
- 열거형은 특정 클래스나 구조체의 기능을 지원하기 위해 생성되는 경우가 많습니다.
- 유사하게, 더 복잡한 유형의 컨텍스트 내에서 사용하기 위해 유틸리티 클래스 및 구조를 정의하는 것이 편리할 수 있습니다.
- 이를 달성하기 위해 Swift는 중첩 유형을 정의할 수 있도록 하여 지원하는 유형의 정의 내에서 지원 열거, 클래스 및 구조를 중첩합니다.
📌 Nested Types in Action
- 아래 예는 Blackjack 게임에서 사용되는 카드 놀이를 모델링하는 BlackjackCard라는 구조를 정의합니다.
- BlackjackCard 구조에는 Suit 및 Rank라는 두 가지 중첩 열거 유형이 있습니다.
- 블랙잭에서 에이스 카드의 값은 1 또는 11입니다.
- 이 기능은 Rank 열거 내에 중첩된 Values라는 구조로 표시됩니다.
struct BlackjackCard {
enum Suit: Character {
case spades = "♠", hearts = "♡", diamonds = "♢", clubs = "♣"
}
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)
}
}
}
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 열거형은 네 가지 일반적인 카드 한 벌과 해당 기호를 나타내는 원시 Character 값을 설명합니다.
- Rank 열거형은 액면가를 나타내는 원시 Int 값과 함께 13가지 가능한 카드 순위를 설명합니다. (이 원시 Int 값은 Jack, Queen, King 및 Ace 카드에 사용되지 않습니다.)
- 위에서 언급했듯이 Rank 열거형은 Values라고 하는 자체 중첩 구조를 추가로 정의합니다.
- 이 구조는 대부분의 카드가 하나의 값을 갖지만 에이스 카드에는 두 개의 값이 있다는 사실을 요약합니다.
- Values 구조는 이를 나타내는 두 가지 속성을 정의합니다.
- first, of type Int
- second, of type Int?, or “optional Int”
- Rank는 또한 Values 구조의 인스턴스를 반환하는 계산된 속성 values를 정의합니다.
- 이 계산된 속성은 카드의 순위를 고려하고 순위에 따라 적절한 값으로 새 Values 인스턴스를 초기화합니다.
- jack, queen, king, ace에 특별한 값을 사용합니다. 숫자 카드의 경우 순위의 원시 Int 값을 사용합니다
- 숫자 카드의 경우 순위의 원시 Int 값을 사용합니다.
- BlackjackCard 구조 자체에는 두 가지 속성, 즉 순위와 수트가 있습니다.
- 또한 rank와 suit에 저장된 값을 사용하여 카드의 이름과 값에 대한 설명을 작성하는 description이라는 계산된 속성을 정의합니다.
- description 속성은 선택적 바인딩을 사용하여 표시할 두 번째 값이 있는지 확인하고, 표시할 경우 해당 두 번째 값에 대한 추가 설명 세부 정보를 삽입합니다.
- BlackjackCard는 사용자 정의 이니셜라이저가 없는 구조이므로 구조 유형에 대한 Memberwise 이니셜라이저에 설명된 대로 암시적 멤버별 이니셜라이저가 있습니다.
- 이 이니셜라이저를 사용하여 theAceOfSpades라는 새 상수를 초기화할 수 있습니다.
let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
print("theAceOfSpades: \(theAceOfSpades.description)")
- Rank와 Suit는 BlackjackCard 내에 중첩되어 있지만 그 유형은 컨텍스트에서 유추할 수 있으므로 이 인스턴스의 초기화는 케이스 이름(.ace 및 .spades)만으로 열거 케이스를 참조할 수 있습니다.
- 위의 예에서 description 속성은 Ace of Spades의 값이 1 또는 11임을 올바르게 보고합니다.
📌 Referring to Nested Types
- 정의 컨텍스트 외부에서 중첩 유형을 사용하려면 해당 이름에 중첩된 유형 이름을 접두사로 붙입니다.
letheartSymbol = BlackjackCard.Suit.hearts.rawValue
- 위의 예에서 이는 Suit, Rank 및 Values의 이름이 정의된 컨텍스트에 따라 자연스럽게 한정되기 때문에 의도적으로 짧게 유지할 수 있습니다.