열거형은 가끔 특정 클래스와 구조체의 기능을 지원하기 위해 생성된다. 이와 비슷하게 복잡한 타입의 클래스와 구조체를 사용할 때 그 안에서 모든 것을 구현하는 것이 편리할 수 있다. 즉 해당 블록 안에 또 다른 열거형, 클래스, 구조체를 중첩해서 정의할 수 있다는 말이다. 다른 타입 내에 타입을 중첩하려면 지원하는 타입의 외부 중괄호 안에 정의를 작성하면 된다.
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가지 심볼을 나타내고 있고, Rank 열거형은 카드에 적힌 숫자를 나타내고 있다.
다른 rank는 한가지의 값을 가지지만 ace는 두가지의 값을 가진다.
Rank는 Values 구조의 인스턴스를 반환하는 계산 프로퍼티를 정의한다.이 계산 프로퍼티는 카드의 순위를 고려하고 적절한 새 Values 인스턴스를 초기화합니다.
let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
print("theAceOfSpades: \(theAceOfSpades.description)")
// Prints "theAceOfSpades: suit is ♠, value is 1 or 11
콘텍스트 외부에서 중첩된 타입을 사용하려면 해당 이름에 중첩된 타입의 이름을 접두사로 붙여야 한다.
let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
// heartsSymbol is "♡"