Swift 列舉 (Enumerations)

列舉 (Enum) 為一組相關的值定義了一個通用的型別,讓你在程式碼中能以此類推地安全使用這些值。

如果你熟悉 C 語言,你會發現 Swift 的 Enum 遠比 C 強大。Swift 的 Enum 不僅僅是整數別名,它還可以擁有方法 (Methods)、計算屬性 (Computed Properties),甚至是帶有參數的關聯值 (Associated Values)。

定義 Enum

使用 enum 關鍵字:

enum CompassPoint {
    case north
    case south
    case east
    case west
}

使用時,如果型別已經確定,可以省略 Enum 名稱直接用點語法:

var directionToHead = CompassPoint.west
directionToHead = .east // 因為已經知道型別,可以省略 CompassPoint

搭配 Switch 使用

Enum 與 Switch 是絕配。記得 Switch 必須涵蓋所有情況 (Exhaustive):

switch directionToHead {
case .north:
    print("Lots of planets have a north")
case .south:
    print("Watch out for penguins")
case .east:
    print("Where the sun rises")
case .west:
    print("Where the skies are blue")
}

關聯值 (Associated Values) - 強大特性

Swift 的 Enum 成員可以儲存自定義的資料。這讓 Enum 變成了類似「變體 (Variant)」或「標籤聯合 (Tagged Union)」的結構。

例如,定義一個條碼型別,它可以是 UPCA 格式 (四個整數) 或 QR Code 格式 (一個字串):

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")

如何在 Switch 中取出這些值?使用 letvar 綁定:

switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
    print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
    print("QR Code: \(productCode).")
}

原始值 (Raw Values)

Enum 成員可以預先被賦予預設值 (稱為原始值),這些值必須是相同型別 (如 Int, String)。

enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
// Swift 會自動遞增:venus 是 2, earth 是 3...

let earthsOrder = Planet.earth.rawValue // 得到 3

使用 init?(rawValue:) 來從原始值建立 Enum 實例 (回傳的是 Optional):

let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet 是 Planet? 型別,值為 Planet.uranus