열거형은 보통 클래스나 구조체의 기능을 지원해주기 위해서 쓰이는 경우가 많다.
구조체와 클래스도 더 복잡한 타입 안에서 쓰이기 위해서 정의될 수 있음!
이걸 위해서 Swift는 nested types 라는 걸 정의해 주는데, 열거형, 클래스, 구조체를 얘네가 지원하는 또다른 타입 안에서 정의할 수 있도록 해 주는거임!
nest 하기 위해서는 그냥 지원받는 타입 중괄호 안에다가 정의해 주면 됨. 간단하쥬?
요건 블랙잭이라는 게임에서 쓰는 카드에 관한 구조체임! 어떤 카드가 얼마의 값을 갖고 있는지 알려줄 수 있다.
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 이니셜라이저를 사용한다.
이 nested type을 밖에서 접근해보자.
젤 바깥 구조체나 클래스부터 불러줘야 함.
let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
// heartsSymbol is "♡"
요런식으로!