在許多編程語言中都存在的枚舉類型,基本都是用于定義一個(gè)具有一組數(shù)據(jù)的值拱她,且這些值是可以枚舉的。那么Swift中我們該如何定義并使用枚舉類型呢?我們從以下3個(gè)方面對Swift3中的枚舉進(jìn)行梳理擎椰。
Swift3中枚舉的3種形式
1. 無raw value且無associated value
(1)定義無raw value且無associated value的枚舉
這種枚舉類型的定義非常簡單,例如:
enum SwitchState {
case ON
case OFF
}
它定義了開關(guān)的兩種狀態(tài): ON, OFF创肥。另外达舒,它還有一種更簡潔的定義方式:
enum SwitchState {
case ON, OFF
}
(2)初始化及使用無raw value且無associated value類型的枚舉
示例:
var state = SWitchState.ON
switch state {
case .ON: print("This is ON state.")
case .OFF: print("This is OFF state.")
}
2. 有raw value
它用于給枚舉中定義的各個(gè)對象預(yù)先定義一個(gè)值。
(1)定義有raw value的枚舉
enum ASCIIControlCharacter: Character {
case tab = "\\t"
case lineFeed = "\\n"
case carriageReturn = "\\r"
}
它定義了一個(gè)包含一系列ASCII字符的枚舉類型叹侄,同時(shí)給其中的每個(gè)對象預(yù)先定義了一個(gè)字符串類型的值巩搏。如果預(yù)先定義的值的類型一致,那么我們可以用更簡潔的方式定義趾代,例如:
enum CompassPoint: String {
case north, south, east, west
}
如果預(yù)先定義的值是Int類型贯底,且值是遞增的,那么我們可以用如下方式定義:
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
(2)使用raw value 初始化有raw value的枚舉
let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet is of type Planet? and equals Planet.uranus
(3)使用有raw value的枚舉的方式
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"
關(guān)于raw value需要注意的地方如下:
- 枚舉中定義的各值所對應(yīng)的raw value均是常量撒强,不可變化且互不相同丈甸;
- raw value對應(yīng)的數(shù)據(jù)類型只能是String, Character, Int 或者Float類型。
3. 有associated value
在定義枚舉的時(shí)候注入一個(gè)與枚舉值相關(guān)聯(lián)的數(shù)據(jù)尿褪,這個(gè)數(shù)據(jù)以構(gòu)造方法的形式注入到對象中睦擂。
(1)定義有associated value的枚舉
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
(2)初始化及使用有associated value的方式
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
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."
關(guān)于Associated value需要注意如下兩點(diǎn):
- 關(guān)聯(lián)的數(shù)據(jù)變量可以是任意類型,且枚舉內(nèi)定義的值的類型可以不同杖玲;
- 數(shù)據(jù)是變量而非常量顿仇。
Swift3中2個(gè)特殊的枚舉類型
1. Optional
(1)Optional的枚舉本質(zhì)
要定義一個(gè)Optional類型的變量有兩種方式, 第一種方式,
let userName: Optional
第二種方式是第一種方式的語法糖形式摆马,這也是最常用的定義optional的方式:
let studentName: String?
剝開事物看本質(zhì)臼闻,對于Optional其實(shí)質(zhì)就是枚舉類型《诓桑看一下蘋果官方文檔對于optional的定義:
public enum Optional : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
...
}
根據(jù)定義述呐,我們可以看到Optional的本質(zhì)就是枚舉類型。
(2)空虛的nil
nil是Optional枚舉實(shí)例的一個(gè)值蕉毯,即上段代碼中的'None'值乓搬。nil有別于其它語言中的null值思犁,以及OC中的nil值,它僅僅表示的是該對象不包含值进肯,而并非指向一個(gè)不存在的對象激蹲。
關(guān)于nil的幾個(gè)注意點(diǎn):
- 可以給任意類型的Optional對象設(shè)置為nil,而不僅僅是class類型江掩;
- Optional對象的默認(rèn)值為nil学辱;
- 不能給非Optional類型的變量賦值為nil
(3)?與环形!兄弟
'?'和'!'兄弟是一對非常有趣的修飾符策泣,用途非常普遍。在swift開發(fā)中抬吟,你可以經(jīng)匙沤担看到它們兄弟在代碼中出沒的身影,可以說哪哪都是拗军。為什么說它們有趣呢任洞?因?yàn)樗鼈冇兄浅F婷畹墓δ埽瑢τ贠ptional類型的使用非常關(guān)鍵发侵。'?'和'!'都可以用于變量聲明以及表達(dá)式中交掏,但是有著各自的作用。
用途一:定義optional變量
'?'定義的變量是optional類型刃鳄,如:let studentName: String?
'!'定義的變量也是optional類型盅弛,如:let studentName: String!
, 然而與'?'定義的變量不同的是,'?'定義的變量在使用時(shí)需要使用'!'進(jìn)行解包叔锐,而使用'!'定義的變量無需解包就可以使用挪鹏。總之愉烙,'!'定義變量的方式可以看成是使用'?'定義變量并使用'!'解包的快捷方式讨盒。需要注意的是我們應(yīng)確保使用'!'定義的變量時(shí)刻有具體的值,否則使用時(shí)會造成crash步责。用途二:用于表達(dá)式中解包
'!'作用于表達(dá)時(shí)中時(shí)主要用于解包返顺,例如:
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
let john = Person()
let roomCount = john.residence!.numberOfRooms
// this triggers a runtime error
'?'主要用于optional chain表達(dá)中,作用也是解包蔓肯。如果當(dāng)前值為nil時(shí)表達(dá)時(shí)返回nil遂鹊,且不會造成crash,例如:
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
let john = Person()
//let roomCount = john.residence!.numberOfRooms
// this triggers a runtime error, the right way is as the following:
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \\(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."
(4)解包的三種方式
- 解包的方法一:'!'運(yùn)算符
例如:
var userName: String? = "Mike"
print("The user name is \\(userName!)")
- 解包的方法二:optional binding:
if let {}
例如:
var userName: String? = "Mike"
if let name = userName {
print("The user name is \\(name)")
}
- 解包的方法三:optional chain:
如前所述蔗包,我們可以使用optional chain進(jìn)行解包秉扑,這里不再具體闡述。
2. 迭代枚舉
迭代枚舉其實(shí)是具有associated value類型枚舉的一個(gè)特例调限。迭代枚舉是一個(gè)非常有意思的語法舟陆,類似于函數(shù)的嵌套迭代误澳,它允許在枚舉定義Associated value的時(shí)候,將其值定義為與當(dāng)前枚舉相同的數(shù)據(jù)類型吨娜,從而形成了一種迭代的特征。定義如下:
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect 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)
}
}
print(evaluate(product))
// Prints "18"
Swift3中枚舉的面向?qū)ο?/h4>
枚舉類型在swift中屬于一等類型淘钟,它和class以及struct共同組成swift的面向?qū)ο蟮娜髷?shù)據(jù)類型宦赠。枚舉類型雖然是值類型,但是它還是具有很多面向?qū)ο蟮奶卣鳎?/p>
- 有構(gòu)造方法米母,可以通過使用構(gòu)造方法初始化勾扭。
- 可以定義computed屬性;
- 可以定義實(shí)例方法铁瞒;
- 可以實(shí)現(xiàn)接口妙色;
- 可以被擴(kuò)展。
鑒于篇幅與內(nèi)容的原因慧耍,具體的內(nèi)容將會在之后的swift面向?qū)ο蟮母鱾€(gè)專題中分別總結(jié)身辨。下一篇文章將會總結(jié)元組類型,即:Swift3知識梳理(二):元組類型芍碧。