Swift 中枚舉的特點(diǎn):
- 不必給每一個(gè)枚舉成員提供一個(gè)值。(枚舉的 case 默認(rèn)就是一個(gè)值)
- 枚舉的值可以是
字符串字符整形值浮點(diǎn)值 - 枚舉成員可以指定任意類型的關(guān)聯(lián)值存儲(chǔ)到枚舉的成員中。
- 枚舉中可以有函數(shù)
- 計(jì)算屬性: 提供枚舉的附加信息。
- 實(shí)例方法: 給 枚舉值(case) 提供相應(yīng)的功能
- 構(gòu)造方法: 給枚舉提供初始值
- 可以遵守協(xié)議:提供標(biāo)準(zhǔn)功能。
枚舉的語(yǔ)法
使用 enum 關(guān)鍵字來(lái)定義一個(gè)枚舉:
enum SomeEnumeration {
// 枚舉定義的 case 放在這里
}
example 1
// CompassPoint 是枚舉的類型
enum CompassPoint {
// 使用 case 來(lái)定義一個(gè)枚舉實(shí)例
case North
case South
case East
case West
}
注意點(diǎn):
Swift 的枚舉不會(huì)被賦值一個(gè)默認(rèn)的整形值。例如 objc 中的 0,1,2,3 等。
在example1 中 枚舉變量的值就是:North,South,East 和 West
多個(gè)成員值可以出現(xiàn)在同一行上,用逗號(hào)隔開:
enum Planet {
case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
每一個(gè)枚舉定義了一個(gè)全新的類型。(和類,結(jié)構(gòu)體一樣)
枚舉變量使用單數(shù)名稱。
獲取枚舉的實(shí)例
var directionToHead = CompassPoint.West
// 修改枚舉實(shí)例(由于類型為 CompassPoint ,類型推斷可以推斷出來(lái),所有可以直接使用 點(diǎn)語(yǔ)法。 )
directionToHead = .East
** 枚舉和 Switch 配合使用 **
- Switch 語(yǔ)句必須 窮舉所有 的情況。當(dāng)不窮舉的時(shí)候回導(dǎo)致編制出錯(cuò)。
- 可以使用 default 語(yǔ)句來(lái)處理 case 沒有白涵蓋的枚舉變量。
關(guān)聯(lián)值
(我的簡(jiǎn)單理解,關(guān)聯(lián)值就是枚舉的 case 變?yōu)樵鏀?shù)據(jù))
// Barcode 枚舉類型
enum Barcode {
// 具有 (Int, Int, Int, Int) 類型的關(guān)聯(lián)值(元祖)UPCA 為元祖的名稱
case UPCA(Int, Int, Int, Int)
// 具有 (String) 類型的關(guān)聯(lián)值(元祖)QRCode 為元祖的名稱
case QRCode(String)
}
// 關(guān)聯(lián)值的使用
var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)
// 修改變量的值
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
// 簡(jiǎn)單條線碼掃描的實(shí)現(xiàn)(太雞巴酷了)
switch productBarcode {
case .UPCA(let numberSystem, let manufacturer, let product, let check):
print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
case .QRCode(let productCode):
print("QR code: \(productCode).")
}
// 輸出 "QR code: ABCDEFGHIJKLMNOP."
// 簡(jiǎn)潔用法
switch productBarcode {
case let .UPCA(numberSystem, manufacturer, product, check):
print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
case let .QRCode(productCode):
print("QR code: \(productCode).")
}
// 輸出 "QR code: ABCDEFGHIJKLMNOP."
原始值 和 值操作
枚舉成員可以被默認(rèn)值(稱為原始值)預(yù)填充,這些原始值的類型必須相同。
有點(diǎn)回到 objc 時(shí)代,但是又有很大的不同。
枚舉的值可以是 字符串 字符 整形值 浮點(diǎn)值
// 原始值的類型為 Character
enum ASCIIControlCharacter: Character {
case Tab = "\t"
case LineFeed = "\n"
case CarriageReturn = "\r"
}
原始值和關(guān)聯(lián)值的不同:
- 原始值必須預(yù)先填充(填充的值類型必須一致)
- 關(guān)聯(lián)值是后期填充的 (值的類型可以不一致)
隱式賦值
enum Planet: Int {
// 后面的值會(huì)一次填充
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
使用字符串作為枚舉類型的原始值時(shí),每個(gè)枚舉成員的隱式原始值為該枚舉成員的名稱
enum CompassPoint: String {
case North, South, East, West
}
// 用起來(lái)好雞巴爽
let sunsetDirection = CompassPoint.West.rawValue
// sunsetDirection 值為 "West"
枚舉成員的rawValue屬性可以訪問(wèn)該枚舉成員的原始值:
let earthsOrder = Planet.Earth.rawValue
// earthsOrder 值為 3
let sunsetDirection = CompassPoint.West.rawValue
// sunsetDirection 值為 "West"
使用原始值初始化枚舉實(shí)例
let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet 類型為 Planet? 值為 Planet.Uranus
遞歸枚舉
丫的,沒看懂。我靠。
遞歸枚舉(recursive enumeration)是一種枚舉類型。
它有一個(gè)或多個(gè)枚舉成員使用該枚舉類型的實(shí)例作為關(guān)聯(lián)值。使用遞歸枚舉時(shí),編譯器會(huì)插入一個(gè)間接層。你可以在枚舉成員前加上indirect來(lái)表示該成員可遞歸。
enum ArithmeticExpression {
case Number(Int)
indirect case Addition(ArithmeticExpression, ArithmeticExpression)
indirect case Multiplication(ArithmeticExpression, ArithmeticExpression)
}
// 在枚舉類型開頭加上indirect關(guān)鍵字來(lái)表明它的所有成員都是可遞歸的
indirect enum ArithmeticExpression {
case Number(Int)
case Addition(ArithmeticExpression, ArithmeticExpression)
case Multiplication(ArithmeticExpression, ArithmeticExpression)
}
上面定義的枚舉類型可以存儲(chǔ)三種算術(shù)表達(dá)式:純數(shù)字、兩個(gè)表達(dá)式相加、兩個(gè)表達(dá)式相乘。
單純的遞歸枚舉是沒有什么意義的。
遞歸枚舉結(jié)合遞歸函數(shù)才有意義。
let five = ArithmeticExpression.Number(5)
let four = ArithmeticExpression.Number(4)
let sum = ArithmeticExpression.Addition(five, four)
let product = ArithmeticExpression.Multiplication(sum, ArithmeticExpression.Number(2))
// 這個(gè)才是功能的具體實(shí)現(xiàn)
func evaluate(expression: ArithmeticExpression) -> Int {
switch expression {
case .Number(let value):
return value
case .Addition(let left, let right):
// 繼續(xù)函數(shù)的調(diào)用
return evaluate(left) + evaluate(right)
case .Multiplication(let left, let right):
// 繼續(xù)函數(shù)的調(diào)用
return evaluate(left) * evaluate(right)
}
}
print(evaluate(product))
// 輸出 "18"