標籤:
枚舉
一個枚舉為一組相關聯的值定義一個通用類型,並且讓你可以在代碼中型別安全地操作這些值。
C中的枚舉將關聯的名字指派給一系列整型值。Swift中的枚舉類型更為活潑,並不需要為每個成員指定值,如果指定值(raw value),這個值可以是String或者Character、整型或者浮點型。
此外,每個枚舉成員可以指定不同數量的任意類型的關聯值儲存起來。這有點像其他語言裡的聯合。你可以定義一個普通的一系列關聯值的集合作為一個枚舉的一部分,每個枚舉都可以有一個適當類型的不同集合。
在Swift中,枚舉類型是一等類型(first class),他們擁有很多以前只有類才擁有的特性,比如屬性用以給枚舉的當前值提供額外的資訊,以及執行個體方法給枚舉所代表的值提供操作。枚舉類型還可以提供初始化方法來提供初始化成員值,也可以被擴充來增加原始操作之外的操作,還可以遵守協議來提供標準操作。
枚舉文法
用enum關鍵字來建立枚舉,將所有的定義放在一對大括弧內部:
enum CompassPoint { case North case South case East case West}
case關鍵字意味著一行新的成員值就要被定義了,和C語言不一樣的是,Swift中的枚舉成員並不會在建立的時候就被賦給一個整型值,上面的例子中,North並不隱式地等於0,它們都是完全合法的值,都是一個明確定義的資料類型CompassPoint。
同一個case行可以有多個值,用逗號隔開即可。
像Swift中的其他資料類型名稱一樣,枚舉型的名字應該以大寫字母開頭。
當把枚舉成員賦值給某個變數後,這個變數的資料類型就可以被推斷出為這個枚舉類型,此後可以用簡寫的點文法來改變其值了:
var directionToHead = CompassPoint.WestdirectionToHead = .East
用switch語句匹配枚舉值:
directionToHead = .Southswitch directionToHead {case .North: println("Lots of planets have a north")case .South: println("Watch out for penguins")case .East: println("Where the sun rises")case .West: println("Where the skies are blue")}// prints "Watch out for penguins”
正如之前控制流程中介紹的,當用switch語句處理枚舉類型時,它必須全面的,比如如果省略掉case .West,那麼就無法編譯,因為switch語句並沒有考慮到完整的枚舉成員。這就防止了不小心漏掉了枚舉成員。當然,在無法覆蓋所有枚舉成員的情況下,可以用一個default分支來處理。
關聯值
前面的例子中,枚舉成員都是自己本身作為自己的值。此外,還可以把變數/常量賦值給枚舉成員,然後在其他地方使用它。但是,有時候會需要依靠這些成員值儲存一些其他類型的關聯值,這使得你可以依靠這些成員值儲存額外的自訂資訊,並且在每次使用成員時允許這個資訊是不一樣的。
你可以定義枚舉儲存任何已經定義的資料類型的關聯值,並且每個枚舉成員的關聯值可以是不同類型的。比如下面的例子,定義了庫存碼的枚舉類型,它有兩個成員,一個代表一維條碼(它總是可以用4個整型數字來標識),一個代表二維碼(它總是可以用一個字串來標識):
enum Barcode { case UPCA(Int, Int, Int, Int) case QRCode(String)}
這裡,枚舉成員都有各自的關聯值,定義的時候只需要指明關聯值的類型,不需要給定值。這樣,新的Barcode類型變數就可以建立為:
var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)
這裡建立了一個變數,賦給它的值是一個有用關聯元組(8, 85909, 51226, 3)的Barcode.UPCA,在此之後,這個變數就可以被賦值為不同的Barcode類型值了,比如:
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
不同的Barcode類型仍然可以像之前那樣在switch語句中被檢查,這次,關聯值可以被取出來成為switch語句的一部分。可以將關聯值作為常量或者變數取出來以便在case體內部使用:
switch productBarcode {case .UPCA(let numberSystem, let manufacturer, let product, let check): println("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")case .QRCode(let productCode): println("QR code: \(productCode).")}// prints "QR code: ABCDEFGHIJKLMNOP.”
如果所有的關聯值都是作為常量/變數被取出,則不需要在每個關聯值前都寫上var/let,將關鍵字提到前面:
switch productBarcode {case let .UPCA(numberSystem, manufacturer, product, check): println("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")case let .QRCode(productCode): println("QR code: \(productCode).")}// prints "QR code: ABCDEFGHIJKLMNOP.”
原始值(Raw Values)
如前所述,枚舉成員可以定義不同類型的關聯值。此外,還可以枚舉成員也可以給定預設值(被稱為raw value),這些值必須是同一類型的。比如:
enum ASCIIControlCharacter: Character { case Tab = "\t" case LineFeed = "\n" case CarriageReturn = "\r"}
注意原始值和關聯值之間的區別,原始值是在定義枚舉類型的時候就給出的,並且之後始終保持一致,關聯值在定義枚舉類型的時候並沒有給出,而是在建立枚舉類型變數的時候才賦予常量或者變數值。
原始值可以是字串、字元、整數、浮點數。每個原始值必須在枚舉聲明內部是唯一的。如果原始值是整形的,那麼如果有的成員沒有賦原始值,系統會自動自增整形值賦給它們。比如:
enum Planet: Int { case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune}
這時系統會自動給後續成員依次賦原始值。通過rawValue可以擷取成員的初始值,比如:
let earthsOrder = Planet.Earth.rawValue// earthsOrder is 3
如果定義了一個有原始實值型別的枚舉類型,枚舉會自動得到一個接受原始實值型別參數並返回一個枚舉成員或者nil的初始化方法,可以使用該方法視圖建立一個枚舉執行個體:
let possiblePlanet = Planet(rawValue: 7)// possiblePlanet is of type Planet? and equals Planet.Uranus
並不是所有的整型數都能在枚舉內部找到匹配的成員,所以,這個初始化方法返回的是可選枚舉成員(optional enumeration member),
Swift學習筆記十