列挙型は特定のクラスや構造体の機能をサポートする生成されます。同様に、より複雑な型の中で使用するためだけにユーティリティなクラスを定義することがあります。これを実現するためSwiftはnested typesを用意しています。本体をサポートする列挙型・クラス・構造体を本体の型の定義内に定義することができます。
ある型を別の型の入れ子(ネスト)にするには、別の型の本体内にその型の定義を記述します。
Nested Typesのアクション
sample1-1はBlackjackCard構造体を定義しています。トランプゲームのブラックジャックがモデルです。BlackjackCard構造体は二つの入れ子の列挙型SuitとRankを含んでいます。
ブラックジャックではAceのカードは1あるいは11、どちらでも評価できます。この機能はValues構造体で表現します。Values構造体はRank列挙型の中に入れ子します。
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列挙型は一般的なトランプの四つの絵柄を表現します。それぞれのケースがCharacter型のraw valueを持っています。
Rank列挙型は13の出現可能性のあるカードのランクを表現し、それぞれのカードの番号を表すInt型のraw valueを持っています。このraw valueはJack,Queen,King,Aceでは使われません。使われないが、raw value自体は
- Jack—>11
- Queen—>12
- King—>13
- Ace—>14
が自動的に割り振られている。
Rank列挙型は、自身の中にさらに入れ子でValues構造体を定義しています。この構造体で、「Aceは二つの値(1 or 11)を持ち、それ以外のカードは一つの値を持つ」という事実をカプセル化します。Values構造体は以下の二つのプロパティでその事実を表現します。
- first,Int型
- second,Int?型(Optional<Int>型)
列挙型Rankはvaluesというコンピューテドプロパティを持ちます。このプロパティはValues構造体のインスタンスを返します。このコンピューテドプロパティvaluesはカードのランクを把握して、そのランクに対応する新しいValues構造体のインスタンスを生成(イニシャライズ)します。
BlackjackCard構造体自体には二つのプロパティ、rankとsuitがあります。それとコンピューテドプロパティdescriptionを定義しています。カードの名前(シンボル)と値を表す説明を組み立てるためにrankとsuitの値を使用します。オプショナルバインディングを使ってvaluesのsecondプロパティがnilでない場合(aceのみ)にそれを表示するようにしています。
BlackjackCard構造体は独自のイニシャライザを定義していないので、自動的にメンバワイズイニシャライザが用意されます。新しい定数theAceOfSpadesに、新しいBlackjackCardインスタンスを生成し代入することができます。
let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades) print("theAceOfSpades: \(theAceOfSpades.description)") // Prints "theAceOfSpades: suit is ♠, value is 1 or 11"
工事中
参考
https://docs.swift.org/swift-book/LanguageGuide/NestedTypes.html