Enumerations

Raw Values

在 Swift 中也可以定義跟 c 語言很像的 enumerations,我們定義有 raw valueenumeration 如下:

enum Planet: Int {
   case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

我們可以得到 enumraw value

let earthNumber = Planet.Earth.toRaw()
// earthNumber is 3

其中 toRaw() 是 keyword,會回傳 raw value


當然不只這樣,Swift 中還可以給 enum 不同的型態的 raw value

enum ControlCharacter: Character {
   case Tab = "\t"
   case Linefeed = "\n"
   case CarriageReturn = "\r"
}

let characterType = ControlCharacter.Tab.toRaw()
// characterType is '"\t"'

Without Raw Value

但是有時候 raw value 根本用不到,我們只想要有不一樣的 enum properties,能夠分類就好,因此我們根本不用定義 raw value

enum CompassPoint {
   case North, South, East, West
}

在這個例子中,North 就是 raw value 本身,因此 Swift 會自動幫你推斷出這個 enum 沒有 raw value,因此也沒有 .toRaw() 可以呼叫。


另外在 Swift 中,還有一個更方便的地方,利用 Type Inference 可以更簡單的操作 enum:

enum CompassPoint {
   case North, South, East, West
}

var directionToHead = CompassPoint.West
// directionToHead is inferred to be a CompassPoint

directionToHead = .East

以上的範例中,Swift 幫你推論出 directionToHead 的型態為 CompassPoint。因此,如果要改變 directionToHead 的內容,只要加上 .East 就可以了,不用再寫成 CompassPoint.East,超級方便的!

這有什麼好處呢?這個功能在開發 iOS 程式時超方便,看一下範例就知道:

let label = UILabel()
label.textAlignment = .Right

我們想要改變 labeltextAlignment,不用知道 textAlignment 的型態是什麼,只要用 . 就會跑出 enum 的選項讓我選擇,真是方便太多啦!

Associated Values

Swift 中 enum 可以做的事情更多,我們可以給 enum 一個相關的參數 (Associated Values)。

假設我們要設計一個 火車狀態查詢 App,火車有兩個狀態:1. OneTime,2. Delayed,此時我們的 enum 如下:

enum TrainStatus {
   case OnTime
   case Delayed(Int)
}

這表示,當我們要設定 Delayed 時,可以給一個 Int 的參數:

enum TrainStatus {
   case OnTime
   case Delayed(Int)
}

var status = TrainStatus.OnTime
// status is inferred to be a TrainStatus

status = .Delayed(42)

要如何使用這個 Delayed(42) 的參數呢?

Enumerations: Initializers And Properties

Swift 中的 enum 也可以定義 initializersproperties,我們定義 description,輸出目前火車的狀態:

enum TrainStatus {
   case OnTime, Delayed(Int)
   init() {
       self = OnTime
   }
   var description: String {
       switch self {
           case OnTime:
               return "on time"
          case Delayed(let minutes):
              return "delayed by \(minutes) minute(s)"
      }
  }
}

其中,我們在 description() 這個 method,使用到 Delayedassociated values。這就是 Swift 中 enum 強大的地方。

最後,我們可以呼叫 description(),就可以得到 delayed 多久了:

var status = TrainStatus()

println("The train is \(status.description)")
// The train is on time

status = .Delayed(42)

println("The train is now \(status.description)")
// The train is now delayed by 42 minute(s)

Nested Types

Swift 的 enum 不一定要獨立定義,可以定義在其他 class 中,可以有 nested types

class Train {
   enum Status {
       case OnTime, Delayed(Int)
       init() {
           self = OnTime
       }
       var description: String { ... }
   }
   var status = Status()
}

這麼一來,Status 就包在 Train 裡面,當 Train 被其他人繼承時也一併包含了 Status,讓開發者在開發時更方便了!

下一篇: Extensions