Swift教程之枚舉類型詳解_Swift

來源:互聯網
上載者:User

枚舉定義了一個常用的具有相關性的一組資料,並在你的代碼中以一個安全的方式使用它們。

如果你熟悉C語言,你就會知道,C語言中的枚舉指定相關名稱為一組整數值。在Swift中枚舉更為靈活,不必為枚舉的每個成員提供一個值。如果一個值(被稱為“原始”的值)被提供給每個枚舉成員,則該值可以是一個字串,一個字元,或者任何整數或浮點類型的值。

另外,枚舉成員可以指定任何類型,每個成員都可以儲存的不同的相關值,就像其他語言中使用集合或變體。你還可以定義一組通用的相關成員為一個枚舉,每一種都有不同的一組與它相關的適當類型的值的一部分。

在Swift中枚舉類型是最重要的類型。它採用了很多以前只有類才具有的特性,如計算效能,以提供有關枚舉的當前值的更多資訊,方法和執行個體方法提供的功能相關的枚舉表示的值傳統上支援的許多功能。枚舉也可以定義初始化,以提供一個初始成員值;可以在原有基礎上擴充擴大它們的功能;並使用協議來提供標準功能。

欲瞭解更多有關這些功能,請參見Properties, Methods, Initialization, Extensions, Protocols

1、枚舉文法

使用枚舉enum關鍵詞並把他們的整個定義在一對大括弧內:

複製代碼 代碼如下:

enum SomeEnumeration {
    // enumeration definition goes here
}

下面是一個指南針的四個點一個例子:

複製代碼 代碼如下:
 
enum CompassPoint {
    case North
    case South
    case East
    case West
}

在枚舉中定義的值(如North,South,East和West)是枚舉的成員值(或成員)。這個例子裡case關鍵字表示成員值一條新的分支將被定義。

Note

不像C和Objective-C,Swift枚舉成員在建立時不分配預設整數值。在上面的例子CompassPoints中North,South,Eath,West不等於隱含0,1,2和3,而是一種與CompassPoint明確被定義的類型卻各不相同的值。

多個成員的值可以出現在一行上,用逗號分隔:

複製代碼 代碼如下:
 
enum Planet {
    case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

每個枚舉定義中定義了一個全新的類型。像其他Swift的類型,它們的名稱(如CompassPoint和Planet)應為大寫字母。給枚舉類型單數而不是複數的名字,這樣理解起來更加容易如:

複製代碼 代碼如下:

var directionToHead = CompassPoint.West

使用directionToHead的類型時,用CompassPoint的一個可能值初始化的推斷。一旦directionToHead被聲明為一個CompassPoint,您可以將其設定為使用更短的.文法而不用再書寫枚舉CompassPoint值本身:

複製代碼 代碼如下:

directionToHead = .East

directionToHead的類型是已知的,所以你可以在設定它的值時,不寫該類型。使用類型明確的枚舉值可以讓代碼具有更好的可讀性。

2、匹配枚舉值與switch語句

你可以使用單個枚舉值匹配switch語句:

複製代碼 代碼如下:

directionToHead = .South
switch 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"

你可以理解這段代碼:

“考慮directionToHead的價值。當它等於North,列印“Lots of planets have a north”。當它等於South,列印“Watch out for penguins”等等。

正如控制流程所描述,Switch語句考慮枚舉的成員,如果省略了West時,這段代碼無法編譯,因為它沒有考慮CompassPoint成員的完整性。Switch語句要求全面性確保枚舉成員,避免不小心漏掉情況發生。

當它不需要為每一個枚舉成員都匹配的情況下,你可以提供一個預設default分支來涵蓋未明確提到的任何成員:

複製代碼 代碼如下:
 
let somePlanet = Planet.Earth
switch somePlanet {
case .Earth:
    println("Mostly harmless")
default:
    println("Not a safe place for humans")
}
// prints "Mostly harmless"

3、關聯值

在上一節中的樣本延時了一個枚舉的成員是如何被定義(分類)的。你可以為Planet.Earth設定一個常量或變數,然後在代碼中檢查這個值。但是,它有時是有用的才能儲存其它類型的關聯值除了這些成員的值。這讓你隨著成員值儲存額外的自訂資訊,並允許在你的代碼中來使用該資訊。

Swift的枚舉類型可以由一些資料類型相關的組成,如果需要的話,這些資料類型可以是各不相同的。枚舉的這種特性跟其它語言中的奇異集合,標籤集合或者變體相似

例如,假設一個庫存跟蹤系統需要由兩種不同類型的條碼來跟蹤產品。有些產品上標有UPC-A代碼格式,它使用數字0到9的一維條碼,每一個條碼都有一個“數字系統”的數字,後跟十“標識符”的數字。最後一位是“檢查”位,以驗證代碼已被正確掃描:

其他產品都貼有二維條碼QR碼格式,它可以使用任何的ISO8859-1字元,並可以編碼字串,最多2,953個字元:

這將是方便的庫存跟蹤系統能夠儲存UPC-A條碼作為三個整數的元組,和QR代碼的條碼的任何長度的字串。

在Swift中可以使用一個枚舉來定義兩種類型的產品條碼,結構可以是這樣的:

複製代碼 代碼如下:

enum Barcode {
    case UPCA(Int, Int, Int)
    case QRCode(String)
}

這可以被理解為:

“定義一個名為條碼枚舉類型,它可以是UPC-A的任一實值型別的關聯值(Int,Int,Int),或QRCode的一個類型為String的關聯值。”

這個定義不提供任何實際的Int或String值,它只是定義了條碼常量和變數當等於Barcode.UPCA或Barcode.QRCode關聯值的類型的時候的儲存形式。

然後可以使用任何一種類型來建立新的條碼:

複製代碼 代碼如下:
 
var productBarcode = Barcode.UPCA(8, 85909_51226, 3)

此樣本建立一個名為productBarcode新的變數,並與相關聯的元組值賦給它Barcode.UPCA的值(8,8590951226,3)。提供的“標識符”值都有整數加底線的文字,85909_51226,使其更易於閱讀的條碼。

同一產品可以分配不同類型的條碼:

複製代碼 代碼如下:
 
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")

在這一點上,原來Barcode.UPCA和其整數值被新的Barcode.QRCode及其字串值代替。_條碼的常量和變數可以儲存任何一個_UPCA或QRCode的(連同其關聯值),但它們只能儲存其中之一在任何指定時間。

不同的條碼類型像以前一樣可以使用一個switch語句來檢查,但是這一次相關的值可以被提取作為switch語句的一部分。您提取每個相關值作為常數(let首碼)或變數(var首碼)不同的情況下,在switch語句的case代碼內使用:

複製代碼 代碼如下:

switch productBarcode {
case .UPCA(let numberSystem, let identifier, let check):
    println("UPC-A with value of \(numberSystem), \(identifier), \(check).")
case .QRCode(let productCode):
    println("QR code with value of \(productCode).")
}
// prints "QR code with value of ABCDEFGHIJKLMNOP."

如果所有的枚舉成員的關聯值的提取為常數,或者當所有被提取為變數,為了簡潔起見,可以放置一個var,或let標註在成員名稱前:

複製代碼 代碼如下:

switch productBarcode {
case let .UPCA(numberSystem, identifier, check):
    println("UPC-A with value of \(numberSystem), \(identifier), \(check).")
case let .QRCode(productCode):
    println("QR code with value of \(productCode).")
}
// prints "QR code with value of ABCDEFGHIJKLMNOP."

4、原始值

在關聯值的條碼的例子示範了一個枚舉的成員如何能聲明它們儲存不同類型的關聯值。作為替代關聯值,枚舉成員可以拿出預先填入預設值(稱為原始值),從而具有相同的類型。

這裡是一個儲存原始的ASCII值命名枚舉成員的一個例子:

複製代碼 代碼如下:
 
enum ASCIIControlCharacter: Character {
    case Tab = "\t"
    case LineFeed = "\n"
    case CarriageReturn = "\r"
}

在這裡,原始值被定義為字元類型的枚舉叫做ASCIIControlCharacter,並設定了一些比較常見的ASCII控制字元。字元值的字串和字元的描述。

注意,原始值是不相同關聯值。原始值設定為預填充的值時,應先在你的代碼中定義枚舉,像上述三個ASCII碼。對於一個特定的枚舉成員的原始值始終是相同的。當你建立一個基於枚舉的常量或變數的新成員的關聯值設定,每次當你這樣做的時候可以是不同的。

原始值可以是字串,字元,或任何整數或浮點數類型。每個原始值必須在它的枚舉中唯一聲明。當整數被用於原始值,如果其他​​枚舉成員沒有值時,它們自動遞增。

下面列舉的是一個細化的早期Planet枚舉,使用原始整數值來表示每個Planet的太陽系的順序:

複製代碼 代碼如下:
 
enum Planet: Int {
    case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

自動遞增意味著Planet.Venus具有2的原始值,依此類推。

訪問其toRaw方法枚舉成員的原始值:

複製代碼 代碼如下:
 
let earthsOrder = Planet.Earth.toRaw()
// earthsOrder is 3

使用枚舉的fromRaw方法來試圖找到一個特定的原始值枚舉成員。這個例子識別Uranus的位置通過原始值為7:

複製代碼 代碼如下:
 
let possiblePlanet = Planet.fromRaw(7)
// possiblePlanet is of type Planet? and equals Planet.Uranus

然而,並非所有可能的Int值都會找到一個匹配的星球。正因如此,該fromRaw方法返回一個可選的枚舉成員。在上面的例子中,是possiblePlanet類型Planet?或“可選的Planet”。

如果你試圖找到一個Planet為9的位置,通過fromRaw返回可選的Planet值將是無:

複製代碼 代碼如下:
 
let positionToFind = 9
if let somePlanet = Planet.fromRaw(positionToFind) {
    switch somePlanet {
    case .Earth:
        println("Mostly harmless")
    default:
        println("Not a safe place for humans")
    }
} else {
    println("There isn't a planet at position \(positionToFind)")
}
// prints "There isn't a planet at position 9"

這個範例使用somePlanet= Planet.fromRaw(9)來嘗試訪問可選集合Planet,在可選Planet集合中設定檢索條件somePlanet,在原始值為9的情況下,不能檢索到位置為9的星球,所有else分支被執行。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.