枚舉語法
enum CompassPoint {
case north
case south
case east
case west
}
多個成員值可以出現(xiàn)在同一行上,用逗號隔開:
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
使用 Switch 語句匹配枚舉值
你可以使用switch語句匹配單個枚舉值:
directionToHead = .south
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")
}
// 打印 "Watch out for penguins”
關(guān)聯(lián)值
枚舉成員可以指定任意類型的關(guān)聯(lián)值存儲到枚舉成員中淫茵,就像其他語言中的聯(lián)合體(unions)和變體(variants)美莫。你可以在一個枚舉中定義一組相關(guān)的枚舉成員页眯,每一個枚舉成員都可以有適當類型的關(guān)聯(lián)值。
如商品上有條碼與二維碼厢呵,
這便于庫存跟蹤系統(tǒng)用包含四個整型值的元組存儲 UPC 碼窝撵,以及用任意長度的字符串儲存 QR 碼。
在 Swift 中襟铭,使用如下方式定義表示兩種商品條形碼的枚舉:
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
以上代碼可以這么理解:
“定義一個名為Barcode的枚舉類型碌奉,它的一個成員值是具有(Int,Int寒砖,Int赐劣,Int)類型關(guān)聯(lián)值的upc,另一個成員值是具有String類型關(guān)聯(lián)值的qrCode哩都】妫”
這個定義不提供任何Int或String類型的關(guān)聯(lián)值,它只是定義了漠嵌,當Barcode常量和變量等于Barcode.upc或Barcode.qrCode時咐汞,可以存儲的關(guān)聯(lián)值的類型盖呼。
然后可以使用任意一種條形碼類型創(chuàng)建新的條形碼,例如:
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
上面的例子創(chuàng)建了一個名為productBarcode的變量碉考,并將Barcode.upc賦值給它塌计,關(guān)聯(lián)的元組值為(8, 85909, 51226, 3)。
同一個商品可以被分配一個不同類型的條形碼侯谁,例如:
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
這時锌仅,原始的Barcode.upc和其整數(shù)關(guān)聯(lián)值被新的Barcode.qrCode和其字符串關(guān)聯(lián)值所替代。Barcode類型的常量和變量可以存儲一個.upc或者一個.qrCode(連同它們的關(guān)聯(lián)值)墙贱,但是在同一時間只能存儲這兩個值中的一個热芹。
像先前那樣,可以使用一個 switch 語句來檢查不同的條形碼類型惨撇。然而伊脓,這一次,關(guān)聯(lián)值可以被提取出來作為 switch 語句的一部分魁衙。你可以在switch的 case 分支代碼中提取每個關(guān)聯(lián)值作為一個常量(用let前綴)或者作為一個變量(用var前綴)來使用:
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).")
}
// 打印 "QR code: ABCDEFGHIJKLMNOP."
如果一個枚舉成員的所有關(guān)聯(lián)值都被提取為常量报腔,或者都被提取為變量,為了簡潔剖淀,你可以只在成員名稱前標注一個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).")
}
// 輸出 "QR code: ABCDEFGHIJKLMNOP."
原始值
在關(guān)聯(lián)值小節(jié)的條形碼例子中纯蛾,演示了如何聲明存儲不同類型關(guān)聯(lián)值的枚舉成員。作為關(guān)聯(lián)值的替代選擇纵隔,枚舉成員可以被默認值(稱為 ?原始值 ?)預填充翻诉,這些原始值的類型必須相同。
這是一個使用 ASCII 碼作為原始值的枚舉:
enum ASCIIControlCharacter: Character {
case tab = "\t"
case lineFeed = "\n"
case carriageReturn = "\r"
}
原始值可以是字符串捌刮,字符碰煌,或者任意整型值或浮點型值。每個原始值在枚舉聲明中必須是唯一的绅作。
注意
原始值和關(guān)聯(lián)值是不同的芦圾。原始值是在定義枚舉時被預先填充的值,像上述三個 ASCII 碼棚蓄。對于一個特定的枚舉成員堕扶,它的原始值始終不變。關(guān)聯(lián)值是創(chuàng)建一個基于枚舉成員的常量或變量時才設(shè)置的值梭依,枚舉成員的關(guān)聯(lián)值可以變化。
原始值的隱式賦值
在使用原始值為整數(shù)或者字符串類型的枚舉時典尾,不需要顯式地為每一個枚舉成員設(shè)置原始值役拴,Swift 將會自動為你賦值。
例如钾埂,當使用整數(shù)作為原始值時河闰,隱式賦值的值依次遞增1科平。如果第一個枚舉成員沒有設(shè)置原始值,其原始值將為0姜性。
下面的枚舉是對之前Planet這個枚舉的一個細化瞪慧,利用整型的原始值來表示每個行星在太陽系中的順序:
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
當使用字符串作為枚舉類型的原始值時,每個枚舉成員的隱式原始值為該枚舉成員的名稱部念。
下面的例子是CompassPoint枚舉的細化弃酌,使用字符串類型的原始值來表示各個方向的名稱:
enum CompassPoint: String {
case north, south, east, west
}
使用枚舉成員的rawValue屬性可以訪問該枚舉成員的原始值:
let earthsOrder = Planet.earth.rawValue
// earthsOrder 值為 3
let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection 值為 "west"
rawValue還有另外一種用法,你可以使用這個初始化方法來創(chuàng)建一個新的枚舉實例儡炼。
let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet 類型為 Planet? 值為 Planet.uranus
遞歸枚舉
遞歸枚舉是一種枚舉類型妓湘,它有一個或多個枚舉成員使用該枚舉類型的實例作為關(guān)聯(lián)值。使用遞歸枚舉時乌询,編譯器會插入一個間接層榜贴。你可以在枚舉成員前加上indirect來表示該成員可遞歸。
例如妹田,下面的例子中唬党,枚舉類型存儲了簡單的算術(shù)表達式:
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
你也可以在枚舉類型開頭加上indirect關(guān)鍵字來表明它的所有成員都是可遞歸的:
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
要操作具有遞歸性質(zhì)的數(shù)據(jù)結(jié)構(gòu),使用遞歸函數(shù)是一種直截了當?shù)姆绞焦碛丁@缡还埃旅媸且粋€對算術(shù)表達式求值的函數(shù):
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)
}
}
print(evaluate(product))
// 打印 "18"
該函數(shù)如果遇到純數(shù)字,就直接返回該數(shù)字的值沮趣。如果遇到的是加法或乘法運算屯烦,則分別計算左邊表達式和右邊表達式的值,然后相加或相乘房铭。