枚舉
C語(yǔ)言中塞关,C枚舉將相關(guān)名稱分配給一組整數(shù)值抬探,而Swift枚舉不必為每個(gè)枚舉值提供一個(gè)值。若為每個(gè)枚舉值提供了值(稱為原始值)帆赢,則該值可以是字符串小压、字符或任何整數(shù)或浮點(diǎn)類型的值。
枚舉還可以指定與每個(gè)枚舉值一起存儲(chǔ)的任何類型的關(guān)聯(lián)值椰于,這與其他語(yǔ)言中的聯(lián)合或變體一樣怠益。
Swift中的枚舉擁有傳統(tǒng)上僅由類支持的許多功能,例如計(jì)算屬性來(lái)提供當(dāng)前枚舉值的附加信息瘾婿,以及實(shí)例方法來(lái)提供與枚舉值的相關(guān)功能蜻牢。
<br />
枚舉語(yǔ)法
使用Enum關(guān)鍵字聲明枚舉:
enum SomeEnumeration {
// enumeration definition goes here
}
以下是指南針的四個(gè)方向的例子:
enum CompassPoint {
case north
case south
case east
case west
}
使用case關(guān)鍵字引入新的枚舉情況。
注意
與C和Objective-C不同偏陪,Swift的枚舉值不會(huì)在創(chuàng)建時(shí)分配默認(rèn)整數(shù)值抢呆。上述枚舉值不會(huì)隱式地等于0、1竹挡、2镀娶、3。
多個(gè)case可以寫在一行揪罕,用逗號(hào)隔開(kāi):
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
每個(gè)枚舉都是一個(gè)全新的類型梯码,像其它類型一樣,名稱以大寫字母開(kāi)頭好啰,且為單數(shù)而非復(fù)數(shù)名稱轩娶。
var directionToHead = CompassPoint.west
使用枚舉類型將某個(gè)枚舉值初始化時(shí),Swift會(huì)推斷其具體枚舉類型框往,下次重新賦值時(shí)鳄抒,可忽略枚舉類型。使用點(diǎn)語(yǔ)法:
directionToHead = .east
<br />
使用Switch語(yǔ)句匹配枚舉值
使用switch語(yǔ)句匹配單個(gè)枚舉值:
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")
}
// Prints "Watch out for penguins"
switch語(yǔ)句必須包括所有沒(méi)有枚舉值椰弊,否則無(wú)法通過(guò)編譯许溅,確保某個(gè)枚舉情況不會(huì)被意外省略。
使用default涵蓋未明確處理的任何枚舉值:
let somePlanet = Planet.earth
switch somePlanet {
case .earth:
print("Mostly harmless")
default:
print("Not a safe place for humans")
}
// Prints "Mostly harmless"
<br />
關(guān)聯(lián)值
有時(shí)可以將其他類型的值和枚舉值一起關(guān)聯(lián)起來(lái)秉版,與枚舉值一起存儲(chǔ)贤重,并在每次使用該信息時(shí),該信息會(huì)發(fā)生變化清焕。
以下為攜帶關(guān)聯(lián)值的條形碼枚舉:
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
關(guān)聯(lián)值不提供類型的實(shí)際值并蝗,只提供枚舉值存儲(chǔ)的關(guān)聯(lián)值的類型祭犯。
使用一下任一類型創(chuàng)建枚舉值:
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
使用switch提取關(guān)聯(lián)值:
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).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."
關(guān)聯(lián)值全被提取為常量或變量:
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."
<br />
原始值
枚舉值可以使用類型一致的默認(rèn)值(即原始值)填充。
enum ASCIIControlCharacter: Character {
case tab = "\t"
case lineFeed = "\n"
case carriageReturn = "\r"
}
原始值可以是字符串滚停、字符或任何整數(shù)或浮點(diǎn)數(shù)類型沃粗,每個(gè)原始值必須是唯一的。
隱式分配枚舉值
不必為每個(gè)枚舉值顯示分配原始值键畴,Swift會(huì)自動(dòng)分配最盅。
整數(shù)用于原始值時(shí),第一個(gè)枚舉值自動(dòng)設(shè)置為0镰吵,之后遞增1檩禾。
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
上面例子中,Planet.Planet具有顯式原始值1疤祭,其他為隱式枚舉值是在其基礎(chǔ)上遞增1。
字符串作為原始值時(shí)饵婆,每個(gè)枚舉值的隱含原始值是該枚舉值的字符串字面量勺馆。
enum CompassPoint: String {
case north, south, east, west
}
上面例子中,CompassPoint.south的隱式原始值為“south”侨核,以此類推草穆。
使用枚舉類型的rawValue屬性獲取其枚舉值的原始值:
let earthsOrder = Planet.earth.rawValue
// earthsOrder is 3
let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection is "west"
用原始值初始化枚舉值
若使用原始值類型定義枚舉,枚舉會(huì)自動(dòng)創(chuàng)建一個(gè)初始化器搓译,并可通過(guò)原始值的初始化器創(chuàng)建枚舉的實(shí)例悲柱。
let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet is of type Planet? and equals Planet.uranus
然而,并不是所有的原始值都能找到匹配的枚舉值些己,所以原始值初始化器(可失敗的初始化器)總是返回枚舉的可選類型豌鸡,可結(jié)合可選綁定和switch語(yǔ)句處理該可選類型。
let positionToFind = 11
if let somePlanet = Planet(rawValue: positionToFind) {
switch somePlanet {
case .earth:
print("Mostly harmless")
default:
print("Not a safe place for humans")
}
} else {
print("There isn't a planet at position \(positionToFind)")
}
// Prints "There isn't a planet at position 11"
<br />
遞歸枚舉
當(dāng)某個(gè)枚舉值的關(guān)聯(lián)值類型是該枚舉類型時(shí)段标,該枚舉是遞歸枚舉涯冠。
遞歸枚舉有兩種書寫方式:
- 在需要遞歸的枚舉值前加上indirect關(guān)鍵字,給部分枚舉值啟用遞歸逼庞。
`
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
2.在聲明枚舉類型enum關(guān)鍵字前加上indirect關(guān)鍵字蛇更,給所有枚舉值啟用遞歸。
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
創(chuàng)建上述遞歸枚舉實(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))
將遞歸枚舉封裝成遞歸函數(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))
// Prints "18"