天天看點

Swift講解專題九——枚舉

一、引言

在Objective-C語言中,沒有實際上是整型資料,Swift中的枚舉則更加靈活,開發者可以不為其配置設定值類型把枚舉作為獨立的類型來使用,也可以為其配置設定值,可以是字元,字元串,整型或者浮點型資料。
           

二、枚舉文法

Swift中enum關鍵字來進行枚舉的建立,使用case來建立每一個枚舉值,示例如下:
           

//建立姓氏枚舉,和Objective-C不同,Swift枚舉不會預設配置設定值

enum Surname {

case 張
case 王
case 李
case 趙           

}

//建立一個枚舉類型的變量

var myName = Surname.張

//如果可以自動推斷出類型 則枚舉類型可以省略

myName = .李

var myName2:Surname = .王

同樣可以将枚舉值都寫在同一個case中,使用逗号分隔:

enum Planet {

case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune           

枚舉經常會和Switch語句結合使用,示例如下:

switch myName {

case .張:

print("姓氏張")           

case .王:

print("姓氏王")           

case .李:

print("姓氏李")           

case .趙:

print("姓氏趙")           

三、枚舉的相關值

Swift中的枚舉有一個很有意思的特點,其可以設定一些相關值,通過相關值,開發者可以從公用的枚舉值中擷取到傳遞的額外相關值,示例如下:
           

enum Number {

case one(count:Int)
case two(count:Int)
case three(count:Int)
case four(count:Int)           

var num = Number.one(count: 5)

switch num {

//擷取num的相關值           

case Number.one(let count):

print(count)           

default:

print(num)           

//如果一個枚舉值所有的相關中都是常量,let關鍵字也可以提取到括号外面

//擷取num的相關值           

case let Number.one(count):

print(count)           
print(num)           

有了相關值這樣的句法,大大的增加了枚舉的靈活性,例如一個形狀枚舉,可能的枚舉值有矩形,圓形等,矩形的枚舉值就可以提供寬高的相關值,圓形的枚舉值就可以提供半徑的相關值,是開發更加靈活。

四、枚舉的原始值

原始值也可以了解為為枚舉設定一個具體類型,示例如下:
           

enum Char:String {

case a = "A"
case b = "B"
case c = "C"           

//”A“

var char = Char.a.rawValue

注意,如果枚舉是Int類型的,則類似于Objective-C,枚舉的原始值會從第一個開始之後依次遞增:

enum Char:Int{

case a = 0
case b
case c           

//1

var char = Char.b.rawValue

同樣可以通過原始值的方式來進行枚舉對象的建立,示例如下:

case a = 0
case b
case c           

//b

var char2 = Char(rawValue:1)

在通過原始值進行枚舉對象建立的時候,有可能建立失敗,例如傳入的原始值并不存在,這時會傳回Optional值nil。

四、遞歸枚舉

遞歸枚舉是Swift枚舉中一個難于了解的地方,實際上也并非十分難于了解,開發者隻要明白枚舉的實質,遞歸枚舉就很好了解。首先,遞歸是一種算法,可以簡單了解為自己調用自己,而枚舉實際上并不是函數,它并不執行某項運算,它隻是表達一個資料或者說他也可以表達一種表達式,示例如下:
           

enum Expression {

//表示加
case add
//表示減
case mul           

前面有提到過相關值的概念,是以,對于上述例子,可以為add和mul枚舉值添加兩個相關值作為參數。

//表示加
case add(Int,Int)
//表示減
case mul(Int,Int)           

如此,如下的寫法實際上就可以代表一個5+5的表達式:

var exp = Expression.add(5, 5)

還是需要強調一點,這個exp隻是表達了5+5這樣一個約定的表達式,它并沒有真正進行5+5的運算。現在問題就來了,使用如上的枚舉,怎樣來表達類似(5+5)*5這樣的複合表達式呢?可以使用遞歸枚舉來實作,即将(5+5)作為枚舉值得相關值再次建立枚舉,改造如下:

//單值資料
case num(Int)
//表示加 indirect為遞歸枚舉關鍵字
indirect case add(Expression,Expression)
//表示減
indirect case mul(Expression,Expression)           

var exp1 = Expression.num(5)

var exp2 = Expression.num(5)

var exp3 = Expression.add(exp1, exp2)

var exp4 = Expression.mul(exp1, exp3)

上面exp4實際上就表達了(5+5)*5這樣一個過程,注意遞歸的枚舉值必須加上indirect關鍵字來聲明。處理遞歸枚舉最好的方式是通過遞歸函數,示例如下:

func expFunc(param:Expression) -> Int {

//進行枚舉判斷
switch param {
    //如果是單獨數字 直接傳回
case .num(let p):
    return p
    //如果是加法 則進行遞歸加
case .add(let one, let two):
    return expFunc(one)+expFunc(two)
    //如果是乘法 則進行遞歸乘
case .mul(let one, let two):
    return expFunc(one)*expFunc(two)
}           

//50

expFunc(exp4)

如果枚舉中所有的case都是可遞歸的,可以将整個枚舉聲明為可遞歸的:

indirect enum Expression {

//單值資料
case num(Int)
//表示加 indirect為遞歸枚舉關鍵字
case add(Expression,Expression)
//表示減
case mul(Expression,Expression)