Swift/pattern

Swift/パターン/列挙型

enum Direction {  // 列挙型Direction
  case Up         // 列挙型のメンバ (member)
  case Down
  case Right
  case Left
}
enum Direction {
  case Up, Down, Right, Left
}

列挙型のメンバは、たとえばDirection.Up のように「列挙型の名前」.「メンバ名」で表す。

let d = Direction.Up
var x : Direction = .Right
d == x  // false。異なる値なので

列挙型の定義にメソッドを含めることができる。

enum Direction {
  case Up, Down, Right, Left
  func clockwise() -> Direction {     // 時計回りに90度回転した方向
    switch self {
      case .Up: return Right   // 列挙型の内部ではメンバ名を直接参照できる
      case .Down: return Left
      case .Right: return Down
      case .Left: return Up
    }
  }
}
let d = Direction.Up
d.clockwise() == Direction.Down   // false
d.clockwise().clockwise() == Direction.Down   // true

一般的には "Direction.Up" と記述するが、型が推論できる場合には ".Up" と省略ができる。 さらに、列挙型の定義内部では "Up" のようにメンバ名だけて記述できる。

列挙型の内部には、格納型のプロパティは定義できないが、計算型のプロパティは定義できる。 タイププロパティは格納型、計算型どちらも定義でき、また、タイプメソッドも定義できる。

2種類の列挙型

列挙型には次の2種類がある。

  • 値型 : 全メンバが同じデータ型の値を持つ
  • 共用型 : それぞれメンバが異なる構造を持ち、インスタンス毎に値を変えることのできる

値型の列挙型

全てのメンバが同じ型の値を持つように定義できる。 メンバの値はどれも異なっている必要がある。

enum 型名 : 実体型 {  // 実体型になれるのは 整数、実数、Book値、文字列リテラルで初期化できる型のみ。
  case メンバ名 = リテラル   // "= リテラル"の部分はオプション
  case メンバ名 = リテラル
  ...
}
enum Direction : Int {
  case Up = 0, Down, Right, Left
}
let a = Direction.Right
let i = a.rawValue    // i = 2 (Int)
let k = Direction.Down.rawValue    // k = 1 (Int)

実体型 (raw type ) の値からそれに対応する列挙型のインスタンスを得るには、 rawValue: というキーワードの引数を1つ持つイニシャライザを使う。 失敗のあるイニシャライザなので nil が返ってくる可能性があり、オプショナル型となる。

let b: Direction ? = Direction(rawValue:3)
b != Direction.Left     // true
if let c = Direction(rawValue:2) {
  print("\(c.rawValue)")    / 2と表示される
}
enum Direction : Int {
  case Up = 0, Right, Down, Left
  func clockwise() -> Direction {
    let t = (self.rawValue + 1) % 4     // selfはインスタンス自身を表す
    return Direction(rawValue:t)!       // nilになることはない
  }
}

共用型の列挙型

共用型 (union type の列挙型は、実体型を指定しないシンプルな列挙型と、 複数の異なるタプルの構造を併せ持つことができる型である。

enum 型名 {
  case メンバ名 タプル型宣言
  case メンバ名 タプル型宣言
    ...
}
enum WebColor {
  case Name (String)   // 色の名前
  case Code (String)   // 色の名前
  case White, Black, Red   // よく使う色
}
let background = WebColor.Name({indigo")
let turquoise: WebColor = .Code("#40E0D0")
let textColor = WebColor.Black

共用型の列挙型は、自分で == 演算子を定義しない限り、相互に比較できない。

if turquoise == WebColor.Code("#40E0D0")   // エラー
enum Ticket {
  case 切符(Int, Bool, 回数券: Bool)   // 普通券の価格、小人、回数券
  case カード(Int, Bool)              // プリペイドカードの残金、小人
  case 敬老パス                       // 敬老パス
}

caseに記述する括弧の内部はタプルで、項目にキーワードを付けることもできる。

switch t {  // t は Ticket
  case let .切符(fare, flag, _): print("普通券 \(fare) "+ (flag ? "小人" : "大人"))
  case .敬老パス: print("敬老パス")
  case .カード(let r,true) where r < 110: print("カード 残金不足") // 小人の最低運賃
  case .カード(let r,false) where r < 230: print("カード 残金不足") // 大人の最低運賃
  case .カード: print("カード")
}

タプルの要素毎にletを記述することもできる。

  case let .切符(fare, _, 回数券: flag):
  または
  case .切符(let fare,_, 回数券: let flag):

if-case文

[式, ] case パターン = 式 [ where 式 ]
if p == .カード { print("カード") }      // エラー。この記述はできない。
switch p {             // OK
  case .カード: print("カード")
  default: break
}
if case .カード = p {print("カード")}  // OK
if case .カード(let y,_) = t where y > 1200 { print("残金\(y)円のカード") } // where節を持つ例

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-05-25 (水) 14:52:48 (1536d)