Swift3知識點梳理(一):枚舉

在許多編程語言中都存在的枚舉類型,基本都是用于定義一個具有一組數據的值,且這些值是可以枚舉的。那么Swift中我們該如何定義并使用枚舉類型呢?我們從以下3個方面對Swift3中的枚舉進行梳理。

Swift3中枚舉的3種形式


1. 無raw value且無associated value
(1)定義無raw value且無associated value的枚舉
這種枚舉類型的定義非常簡單,例如:

enum SwitchState {
case ON 
case OFF
}

它定義了開關的兩種狀態: 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
它用于給枚舉中定義的各個對象預先定義一個值。
(1)定義有raw value的枚舉

enum ASCIIControlCharacter: Character {
case tab = "\\t"
case lineFeed = "\\n"
case carriageReturn = "\\r"
}

它定義了一個包含一系列ASCII字符的枚舉類型,同時給其中的每個對象預先定義了一個字符串類型的值。如果預先定義的值的類型一致,那么我們可以用更簡潔的方式定義,例如:

enum CompassPoint: String {
case north, south, east, west
}

如果預先定義的值是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"

關于raw value需要注意的地方如下:

  • 枚舉中定義的各值所對應的raw value均是常量,不可變化且互不相同;
  • raw value對應的數據類型只能是String, Character, Int 或者Float類型。

3. 有associated value
在定義枚舉的時候注入一個與枚舉值相關聯的數據,這個數據以構造方法的形式注入到對象中。
(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."

關于Associated value需要注意如下兩點:

  • 關聯的數據變量可以是任意類型,且枚舉內定義的值的類型可以不同;
  • 數據是變量而非常量。

Swift3中2個特殊的枚舉類型


1. Optional
(1)Optional的枚舉本質
要定義一個Optional類型的變量有兩種方式, 第一種方式,
let userName: Optional
第二種方式是第一種方式的語法糖形式,這也是最常用的定義optional的方式:
let studentName: String?
剝開事物看本質,對于Optional其實質就是枚舉類型??匆幌绿O果官方文檔對于optional的定義:

public enum Optional : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
...
}

根據定義,我們可以看到Optional的本質就是枚舉類型。
(2)空虛的nil
nil是Optional枚舉實例的一個值,即上段代碼中的'None'值。nil有別于其它語言中的null值,以及OC中的nil值,它僅僅表示的是該對象不包含值,而并非指向一個不存在的對象。

關于nil的幾個注意點:

  • 可以給任意類型的Optional對象設置為nil,而不僅僅是class類型;
  • Optional對象的默認值為nil;
  • 不能給非Optional類型的變量賦值為nil

(3)?與!兄弟
'?'和'!'兄弟是一對非常有趣的修飾符,用途非常普遍。在swift開發中,你可以經??吹剿鼈冃值茉诖a中出沒的身影,可以說哪哪都是。為什么說它們有趣呢?因為它們有著非常奇妙的功能,對于Optional類型的使用非常關鍵。'?'和'!'都可以用于變量聲明以及表達式中,但是有著各自的作用。

  • 用途一:定義optional變量
    '?'定義的變量是optional類型,如:let studentName: String?
    '!'定義的變量也是optional類型,如:let studentName: String! , 然而與'?'定義的變量不同的是,'?'定義的變量在使用時需要使用'!'進行解包,而使用'!'定義的變量無需解包就可以使用。總之,'!'定義變量的方式可以看成是使用'?'定義變量并使用'!'解包的快捷方式。需要注意的是我們應確保使用'!'定義的變量時刻有具體的值,否則使用時會造成crash。

  • 用途二:用于表達式中解包
    '!'作用于表達時中時主要用于解包,例如:

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表達中,作用也是解包。如果當前值為nil時表達時返回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)解包的三種方式

  • 解包的方法一:'!'運算符
    例如:
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進行解包,這里不再具體闡述。

2. 迭代枚舉
迭代枚舉其實是具有associated value類型枚舉的一個特例。迭代枚舉是一個非常有意思的語法,類似于函數的嵌套迭代,它允許在枚舉定義Associated value的時候,將其值定義為與當前枚舉相同的數據類型,從而形成了一種迭代的特征。定義如下:

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中枚舉的面向對象


枚舉類型在swift中屬于一等類型,它和class以及struct共同組成swift的面向對象的三大數據類型。枚舉類型雖然是值類型,但是它還是具有很多面向對象的特征:

  • 有構造方法,可以通過使用構造方法初始化。
  • 可以定義computed屬性;
  • 可以定義實例方法;
  • 可以實現接口;
  • 可以被擴展。

鑒于篇幅與內容的原因,具體的內容將會在之后的swift面向對象的各個專題中分別總結。下一篇文章將會總結元組類型,即:Swift3知識梳理(二):元組類型。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,885評論 1 10
  • title: "Swift 中枚舉高級用法及實踐"date: 2015-11-20tags: [APPVENTUR...
    guoshengboy閱讀 2,623評論 0 2
  • 出自鄉野中, 往來于鬧市。 為練人情學世故, 萬般未洞明。 轉眼三十已過, 經年又逢不惑。 吃得苦,做得樂, 心事...
    繪享瘦閱讀 374評論 1 1
  • 茉莉花茶:驅寒 蒲公英茶 枸杞茶:滋腎、養肝、潤肺、明目 檸檬草:改善貧血、調和腸胃、調節油脂分泌和降低血脂、緩解...
    踐行學堂閱讀 285評論 0 0