Enumerations are often created to support a specific class or structure’s functionality. Similarly, it can be convenient to define utility classes and structures purely for use within the context of a more complex type. To accomplish this, Swift enables you to define nested types, whereby you nest supporting enumerations, classes, and structures within the definition of the type they support.
열거체는 종종 특정 클래스나 구조체의 기능을 지원하고자 생성합니다. 이와 비슷하게, 순전히 더 복잡한 타입 안에서만 사용할 보조 클래스 및 구조체를 정의한다면 편리할 수 있습니다. 이를 해내고자, 스위프트는 지원할 타입의 정의 안에 지원용 열거체, 클래스, 및 구조체를 중첩하는 것으로, 중첩 타입 (nested types) 을 정의할 수 있게 합니다.
다른 차입 안에 타입을 중첩하려면 지원할 타입의 바깥 중괄호{
안에 타입의 정의를 작성한다. 필요한 만큼 많은 수준의 타입을 중첩할 수 있다.
아래 예제는, 블랙잭 게임 에서 사용할 트럼프 카드를 모델링하는, BlackjackCard
라는 구조체를 정의한다. BlackjackCard
구조체는 Suit
와 Rank
라는 두 개의 중첩 열거체 타입을 담고 있다.
블랙잭의 에이스 카드는 1 이나 11중 어느 하나의 값을 가진다. Rank
열거형 안에 중첩한 Values
라는 구조체로 이런 특징을 나타낸다.
struct BlackjackCard {
// 중첩 Suit 열거형
enum Suit: Character {
case spades = "♠", hearts = "♡", diamonds = "♢", clubs = "♣"
}
// 중첩 Rank 열거형
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 의 프로퍼티 및 메소드
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
원시 값 (rawValue) 과, 일반 트럼프 카드의 네 가지 패(모양)를 함께 설명한다.
Rank
열거형은 자신의 카드(숫자) 값을 나타내는 Int
원시 값과, 트럼프 카드에서 가능한 13 개의 끗수를 함께 설명한다. (잭 (Jack), 퀸 (Queen), 킹 (King), 및 에이스 (Ace) 카드에선 이 Int
원시 값을 사용하지 않는다.)
위에서 언급한 것처럼, Rank
열거형은 자신만의 Values
라는 더 중첩된 구조체를 정의한다. 이 구조체는 대부분의 카드엔 하나의 값만 있지만, 에이스 카드엔 두 개의 값이 있다는 사실을 은닉한다. Values
구조체는 두 개의 프로퍼티를 정의하여 이를 나타낸다.
1. first
프로퍼티: 타입은 Int
second
프로퍼티: 타입은 Int?
, 또는 “옵셔널 Int
”Rank
는 Values
구조체 인스턴스를 반환하는 values
연산 프로퍼티도 정의한다. 이 연산 프로퍼티는 카드의 끗수를 고려하여 자신의 끗수에 기초한 적절한 값으로 새로운 Values
인스턴스를 초기화한다. jack, queen, king, 및 ace 면 특수한 값을 사용한다. 숫자 카드면 끗수의 Int
원시 값을 사용한다.
BlackjackCard
구조체 그 자체도 rank
와 suit
라는 두 프로퍼티를 가진다. description
이라는 연산 프로퍼티도 정의하는데, 이는 rank
와 suit
에 저장한 값을 사용하여 카드 이름과 값의 설명을 제작한다. description
프로퍼티는 옵셔널 바인딩을 사용하여 두 번째 값이 있는 지 검사하고, 값이 있는 경우 그 두 번째 값의 세부적인 추가 설명을 집어 넣는다.
BlackjackCard
는 자신만의 이니셜라이저가 없는 구조체이기 때문에 Memberwise Initializers for Structure Types 에서 설명한 것처럼 암시적인 멤버 이니셜라이저를 가진다. 이 초기자를 사용하여 theAceOfSpades
라는 새로운 상수를 초기화할 수 있다.
let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
print("theAceOfSpades: \(theAceOfSpades.description)")
// "theAceOfSpades: suit is ♠, value is 1 or 11" 를 인쇄함
Rank
와 Suit
가 BlackjackCard
안에 중첩되어 있을지라도 이 타입들은 상황으로 추론할 수 있어서 (.ace 와 .spades 라는) 자신의 case
이름 만으로도 이 인스턴스의 초기화가 열거형 case
를 참조할 수 있다. 위 예제에선, 스페이드 에이스엔 1
또는 11
의 값이 있음을 description
프로퍼티가 올바르게 알려준다.let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
// heartsSymbol 은 "♡" 임