1. 程式人生 > 其它 >Swift文件Chapter 8 列舉

Swift文件Chapter 8 列舉

列舉為一組相關值定義了一個共同的型別,在程式碼中可以以型別安全的方式訪問這些值。

列舉語法

enum enumType{
    case value1
    case value2
    case value3
}

使用case可以定義一個新的列舉值。同時,列舉值是完備的,不會像C語言一樣分配一個預設的整形值。
可以使用逗號分隔在同一行定義多個列舉值。列舉的名字使用大寫字母開頭,並且使用單數。一旦某一個變數被宣告為列舉型別,那麼可以直接使用.訪問成員。如果變數的列舉型別已知,可以在賦值時省略列舉型別,直接用.訪問成員。

使用Switch語句匹配列舉值

Switch語句匹配列舉值時會強制列舉,如果某些值沒有考慮時,編譯就會報錯。不需要匹配的值可以使用default

進行匹配。

列舉值的遍歷

令列舉遵循CaseIterable協議,那麼Swift會為列舉加入allCases屬性。這個屬性可以使用for-in遍歷,同時也可以呼叫allCases屬性的count屬性獲得列舉值個數。遵循協議需要在列舉名後面加上冒號後去使用這個協議。

關聯值

我們可以給我們的列舉值關聯一個值,類似於為列舉值賦值。關聯值的定義如下:

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

關聯值只定義型別,當把列舉值賦值的時候,可以在後面加上括號並賦一個關聯值。

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

這個時候我們在使用switch語句匹配的時候,可以同時獲得關聯值的量:

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).")
}

當所有的關聯值都需要都被提取為變數或者常量,那麼可以在成員名稱前標註一個let

或者var

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

原始值

列舉成員可以被原始值預填充,這些值必須型別一致。這種方法更貼近於C語言中的列舉。
以ASCII碼列舉為例:

enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}

我們定義這個列舉為Character型別的列舉並賦對應值。原始值的型別可以為字串,字元,任意整型和浮點型。

原始值和關聯值是不同的。原始值是在定義列舉時被預先填充的值,像上述三個 ASCII 碼。對於一個特定的列舉成員,它的原始值始終不變。關聯值是建立一個基於列舉成員的常量或變數時才設定的值,列舉成員的關聯值可以變化。

原始值的隱式賦值

  • 整型:每一個列舉值依次加1,如果第一個列舉值不賦初值,列舉值預設為0;
  • 字串:預設賦值和列舉成員的列舉名一致。

使用原始值初始化列舉例項

我們使用enumType(rawValue:)的方式初始化一個列舉值,返回值是一個可選型別,不一定每一個原始值都可以得到對應的列舉。

遞迴列舉

case前加上indirect表明這個成員是可以遞迴的。在enum前加上indirect表明所有的成員都是可以遞迴的。

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}

這樣的遞迴形式就可以進行一個求值運算:

func evaluate(_ expression: ArithmeticExpression) -> Int {
    switch expression {
    case let .number(value):
        return value
    case let .addition(left, right):
        return evaluate(left) + evaluate(right)
    case let .multiplication(left, right):
        return evaluate(left) * evaluate(right)
    }
}