• <menu id="w2i4a"></menu>
  • logo Swift編程語言中文教程

    文檔首頁>>Swift編程語言中文教程>>Swift編程語言中文教程(八):Swift數(shù)據(jù)之枚舉類型

    Swift編程語言中文教程(八):Swift數(shù)據(jù)之枚舉類型


    本頁內(nèi)容包含:

    枚舉定義了一個通用類型的一組相關(guān)的值,使你可以在你的代碼中以一個安全的方式來使用這些值。

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

    此外,枚舉成員可以指定任何類型的相關(guān)值存儲到枚舉成員值中,就像其他語言中的聯(lián)合體(unions)和變體(variants)。你可以定義一組通用的相關(guān)成員作為枚舉的一部分,每一組都有不同的一組與它相關(guān)的適當(dāng)類型的數(shù)值。

    在 Swift 中,枚舉類型是一等(first-class)類型。它們采用了很多傳統(tǒng)上只被類(class)所支持的特征,例如計算型屬性(computed properties),用于提供關(guān)于枚舉當(dāng)前值的附加信息, 實例方法(instance methods),用于提供和枚舉所代表的值相關(guān)聯(lián)的功能。枚舉也可以定義構(gòu)造函數(shù)(initializers)來提供一個初始成員值;可以在原始的實現(xiàn)基礎(chǔ)上擴(kuò)展它們的功能;可以遵守協(xié)議(protocols)來提供標(biāo)準(zhǔn)的功能。

    欲了解更多相關(guān)功能,請參見屬性(Properties),方法(Methods),構(gòu)造過程(Initialization),擴(kuò)展(Extensions)和協(xié)議(Protocols)。

    枚舉語法

    使用enum關(guān)鍵詞并且把它們的整個定義放在一對大括號內(nèi):

    enum SomeEnumeration {
      // enumeration definition goes here
    }

    以下是指南針?biāo)膫€方向的一個例子:

    enum CompassPoint {
      case North
      case South
      case East
      case West
    }

    一個枚舉中被定義的值(例如 North,South,East和West)是枚舉的成員值(或者成員)。case關(guān)鍵詞表明新的一行成員值將被定義。

    注意:
    不像 C 和 Objective-C 一樣,Swift 的枚舉成員在被創(chuàng)建時不會被賦予一個默認(rèn)的整數(shù)值。在上面的CompassPoints例子中,North,South,East和West不是隱式的等于0,1,2和3。相反的,這些不同的枚舉成員在CompassPoint的一種顯示定義中擁有各自不同的值。

    多個成員值可以出現(xiàn)在同一行上,用逗號隔開:

    enum Planet {
      case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Nepturn
    }

    每個枚舉定義了一個全新的類型。像 Swift 中其他類型一樣,它們的名字(例如CompassPoint和Planet)必須以一個大寫字母開頭。給枚舉類型起一個單數(shù)名字而不是復(fù)數(shù)名字,以便于讀起來更加容易理解:

    var directionToHead = CompassPoint.West

    directionToHead的類型被推斷當(dāng)它被CompassPoint的一個可能值初始化。一旦directionToHead被聲明為一個CompassPoint,你可以使用更短的點(.)語法將其設(shè)置為另一個CompassPoint的值:

    directionToHead = .East

    directionToHead的類型已知時,當(dāng)設(shè)定它的值時,你可以不再寫類型名。使用顯示類型的枚舉值可以讓代碼具有更好的可讀性。

    匹配枚舉值和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")
    }
    // 輸出 "Watch out for penguins”

    你可以如此理解這段代碼:

    “考慮directionToHead的值。當(dāng)它等于.North,打印“Lots of planets have a north”。當(dāng)它等于.South,打印“Watch out for penguins”。”

    等等依次類推。

    正如在控制流(Control Flow)中介紹,當(dāng)考慮一個枚舉的成員們時,一個switch語句必須全面。如果忽略了.West這種情況,上面那段代碼將無法通過編譯,因為它沒有考慮到CompassPoint的全部成員。全面性的要求確保了枚舉成員不會被意外遺漏。

    當(dāng)不需要匹配每個枚舉成員的時候,你可以提供一個默認(rèn)default分支來涵蓋所有未明確被提出的任何成員:

    let somePlanet = Planet.Earth
    switch somePlanet {
    case .Earth:
        println("Mostly harmless")
    default:
        println("Not a safe place for humans")
    }
    // 輸出 "Mostly harmless”

    相關(guān)值(Associated Values)

    上一小節(jié)的例子演示了一個枚舉的成員是如何被定義(分類)的。你可以為Planet.Earth設(shè)置一個常量或則變量,并且在之后查看這個值。然而,有時候會很有用如果能夠把其他類型的相關(guān)值和成員值一起存儲起來。這能讓你存儲成員值之外的自定義信息,并且當(dāng)你每次在代碼中使用該成員時允許這個信息產(chǎn)生變化。

    你可以定義 Swift 的枚舉存儲任何類型的相關(guān)值,如果需要的話,每個成員的數(shù)據(jù)類型可以是各不相同的。枚舉的這種特性跟其他語言中的可辨識聯(lián)合(discriminated unions),標(biāo)簽聯(lián)合(tagged unions),或者變體(variants)相似。

    例如,假設(shè)一個庫存跟蹤系統(tǒng)需要利用兩種不同類型的條形碼來跟蹤商品。有些商品上標(biāo)有 UPC-A 格式的一維碼,它使用數(shù)字 0 到 9。每一個條形碼都有一個代表“數(shù)字系統(tǒng)”的數(shù)字,該數(shù)字后接 10 個代表“標(biāo)識符”的數(shù)字。最后一個數(shù)字是“檢查”位,用來驗證代碼是否被正確掃描:

    Swift編程語言中文教程(八):枚

    其他商品上標(biāo)有 QR 碼格式的二維碼,它可以使用任何 ISO8859-1 字符,并且可以編碼一個最多擁有 2,953 字符的字符串:

    Swift編程語言中文教程(八):枚舉

    對于庫存跟蹤系統(tǒng)來說,能夠把 UPC-A 碼作為三個整型值的元組,和把 QR 碼作為一個任何長度的字符串存儲起來是方便的。

    在 Swift 中,用來定義兩種商品條碼的枚舉是這樣子的:

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

    以上代碼可以這么理解:

    “定義一個名為Barcode的枚舉類型,它可以是UPCA的一個相關(guān)值(Int,Int,Int),或者QRCode的一個字符串類型(String)相關(guān)值。”

    這個定義不提供任何Int或String的實際值,它只是定義了,當(dāng)Barcode常量和變量等于Barcode.UPCA或Barcode.QRCode時,相關(guān)值的類型。

    然后可以使用任何一種條碼類型創(chuàng)建新的條碼,如:

    var productBarcode = Barcode.UPCA(8, 85909_51226, 3)

    以上例子創(chuàng)建了一個名為productBarcode的新變量,并且賦給它一個Barcode.UPCA的相關(guān)元組值(8, 8590951226, 3)。提供的“標(biāo)識符”值在整數(shù)字中有一個下劃線,使其便于閱讀條形碼。

    同一個商品可以被分配給一個不同類型的條形碼,如:

    productBarcode = .QRCode("ABCDEFGHIJKLMNOP")

    這時,原始的Barcode.UPCA和其整數(shù)值被新的Barcode.QRCode和其字符串值所替代。條形碼的常量和變量可以存儲一個.UPCA或者一個.QRCode(連同它的相關(guān)值),但是在任何指定時間只能存儲其中之一。

    像以前那樣,不同的條形碼類型可以使用一個 switch 語句來檢查,然而這次相關(guān)值可以被提取作為 switch 語句的一部分。你可以在switch的 case 分支代碼中提取每個相關(guān)值作為一個常量(用let前綴)或者作為一個變量(用var前綴)來使用:

    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).")
    }
    // 輸出 "QR code with value of ABCDEFGHIJKLMNOP.”

    如果一個枚舉成員的所有相關(guān)值被提取為常量,或者它們?nèi)勘惶崛樽兞?,為了簡潔,你可以只放置一個var或者let標(biāo)注在成員名稱前:

    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).")
    }
    // 輸出 "QR code with value of ABCDEFGHIJKLMNOP."

    原始值(Raw Values)

    Associated Values小節(jié)的條形碼例子中演示了一個枚舉的成員如何聲明它們存儲不同類型的相關(guān)值。作為相關(guān)值的替代,枚舉成員可以被默認(rèn)值(稱為原始值)預(yù)先填充,其中這些原始值具有相同的類型。

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

    enum ASCIIControlCharacter: Character {
        case Tab = "\t"
        case LineFeed = "\n"
        case CarriageReturn = "\r"
    }

    在這里,稱為ASCIIControlCharacter的枚舉的原始值類型被定義為字符型Character,并被設(shè)置了一些比較常見的 ASCII 控制字符。字符值的描述請詳見字符串和字符Strings and Characters部分。

    注意,原始值和相關(guān)值是不相同的。當(dāng)你開始在你的代碼中定義枚舉的時候原始值是被預(yù)先填充的值,像上述三個 ASCII 碼。對于一個特定的枚舉成員,它的原始值始終是相同的。相關(guān)值是當(dāng)你在創(chuàng)建一個基于枚舉成員的新常量或變量時才會被設(shè)置,并且每次當(dāng)你這么做得時候,它的值可以是不同的。

    原始值可以是字符串,字符,或者任何整型值或浮點型值。每個原始值在它的枚舉聲明中必須是唯一的。當(dāng)整型值被用于原始值,如果其他枚舉成員沒有值時,它們會自動遞增。

    下面的枚舉是對之前Planet這個枚舉的一個細(xì)化,利用原始整型值來表示每個 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方法來試圖找到具有特定原始值的枚舉成員。這個例子通過原始值7識別Uranus:

    let possiblePlanet = Planet.fromRaw(7)
    // possiblePlanet is of type Planet? and equals Planet.Uranus

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

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

    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)")
    }
    // 輸出 "There isn't a planet at position 9

    這個范例使用可選綁定(optional binding),通過原始值9試圖訪問一個行星。if let somePlanet = Planet.fromRaw(9)語句獲得一個可選Planet,如果可選Planet可以被獲得,把somePlanet設(shè)置成該可選Planet的內(nèi)容。在這個范例中,無法檢索到位置為9的行星,所以else分支被執(zhí)行。

    掃碼咨詢


    添加微信 立即咨詢

    電話咨詢

    客服熱線
    023-68661681

    TOP
    三级成人熟女影院,欧美午夜成人精品视频,亚洲国产成人乱色在线观看,色中色成人论坛 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();