-
Notifications
You must be signed in to change notification settings - Fork 2
Description
열거형은 종종 특정 클래스 또는 구조체의 기능을 지원하기 위해 만들어진다
마찬가지로 보다 복잡한 타입의 문맥에서 사용하기 위해 유틸리티 클래스나 구조체를 정의하는 게 편리할 수 있다
Swift는 이를 위해 중첩 타입(nested type)을 정의할 수 있다
열거형, 클래스, 구조체를 지원되는 타입의 정의 안에서 중첩시킬 수 있다
한 타입을 다른 타입 안에 중첩시키려면 지원되는 타입의 외부 중괄호 안에 타입 정의를 작성한다
필요한 만큼 많은 단계로 타입을 중첩시킬 수 있다
중첩 타입의 사용
아래 예시는 BlackjackCard 구조체를 정의한다
블랙잭 게임에서 사용되는 플레이 카드를 모델링한다
BlackjackCard 구조체는 Suit와 Rank 두 가지 중첩된 열거형 타입을 포함한다
블랙잭에서 에이스 카드는 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 열거형은 네 가지 일반적인 플레이 카드 슈트와 심볼을 표현하는 raw Character 값과 함께 묘사한다
Rank 열거형은 13개의 가능한 플레이 카드 순위를 raw Int 값과 함께 묘사한다
해당 Int 값은 잭, 퀸, 킹, 에이스 카드에는 사용되지 않는다
앞서 언급한 것처럼, Rank 열거형은 그 안에 Values 중첩 구조체를 정의한다
Values 구조체는 대부분의 카드는 하나의 값을, 에이스 카드는 두 개의 값을 가질 수 있다는 사실을 캡슐화한다
Values 구조체는 이를 표현하기 위해 first와 second 두 프로퍼티를 선언한다
-
first, Int 타입
-
second, Int?, 혹은 “optional Int” 타입
Rank는 계산 프로퍼티인 values를 정의하며, Values 구조체의 인스턴스를 반환한다
계산 프로퍼티 values는 카드의 랭크를 고려하고, 이를 기반으로 한 적절한 값으로 새로운 Values 인스턴스를 초기화 한다
잭, 퀸, 킹, 에이스 카드를 위한 특별한 값을 사용한다
숫자 카드의 경우 순위의 원시 Int 값을 사용한다
BlackjackCard 구조체는 rank와 suit 두 프로퍼티를 갖는다.
desciption 계산 프로퍼티도 정의하는데, rank와 suit에 저장된 값을 사용해 카드의 이름과 값을 출력한다
desciption 프로퍼티는 두 번째 값을 보여 줄 수 있는지 확인하기 위해 옵셔널 바인딩을 사용한다
가능할 경우 두 번째 값에 대한 상세 정보를 추가한다
BlackjackCard 구조체에 커스텀 이니셜라이저가 없기 때문에,
Memberwise Initializer for Structure Types에서 설명한 대로
암시적인 멤버 이니셜라이저를 갖게 된다
해당 이니셜라이저를 사용하여 theAceOfSpades 상수를 초기화할 수 있다
let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
print("theAceOfSpades: \(theAceOfSpades.description)")
// Prints "theAceOfSpades: suit is ♠, value is 1 or 11"Rank와 Suit가 BlackjackCard에 중첩된 것이더라도, 타입은 문맥으로부터 추론될 수 있다
따라서, 해당 인스턴스의 초기화는 케이스 이름(.ace와 .spades)에 의해 열거형 케이스를 참조할 수 있다
예시에서 description 프로퍼티는 스페이드의 에이스 값이 1 또는 11임을 올바르게 나타낸다
중첩 타입 참조하기
정의된 컨텍스트 바깥에서 중첩 타입을 사용하려면, 이름 앞에 중첩된 타입의 이름을 붙인다
let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
// heartsSymbol is "♡"위의 예제의 경우 Suite, Rank 및 Values의 이름을 의도적으로 짧게 유지할 수 있다
해당 이름은 정의된 컨텍스트에 따라 자연스럽게 한정되기 때문