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