swift枚举

分享到:

枚举定义了一组相关值的通用类型,并让你能够在你的代码中安全的操作这些值。

如果你熟悉 C 语言,你就会知道,C 语言中的枚举将指定一组整数值的相关名称。在 Swift 中枚举更为灵活,不必为枚举的每个成员提供一个值。如果一个值(被称为“原始”的值)被提供给每个枚举成员,则该值可以是一个字符串,一个字符,或者任何整数或浮点类型的值。

另外,枚举成员可指定要与每个不同成员值一起存储的任何类型相关值,就像其他语言中集合或变体那样。你可将一组通用的相关成员定义为枚举的一部分,每部分都有与其相关的不同的一组适当类型的值。

在 Swift 中,枚举凭本身的力量成为最重要的类型。它们采用了传统上只有类支持的许多特性,如计算性能,以提供有关枚举当前值的更多信息,并采用实例方法以提供与枚举所代表的值相关的功能。枚举也可以定义初始化以提供一个初始成员值;可扩展到超出其原来执行范围的功能超;并可遵照协议提供标准功能。

欲了解更多有关这些功能的信息,请参见属性、方法、初始化、扩展和协议。

枚举句法

你用 enum 关键字介绍枚举并将其整个定义放在一对大括号内:

 
enum SomeEnumeration {
// enumeration definition goes here
}
 

下面是有关指南针四个要点的一个例子:

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

在枚举中定义的值(如,,和 )是枚举的成员值(或成员)。关键字表明将对新一行的成员值进行定义。

注:不像 C 和 Objective-C,Swift 枚举成员在创建时不分配默认整数值。在上面的 CompassPoints 例子中,North,South,East 和 West 不等于隐值 0,1,2 和 3。相反,不同的枚举成员凭本身的力量成为成熟的值,含明确定义的 CompassPoint 类型。

多个成员值可出现在一行上,用逗号隔开:

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

每个枚举定义中定义了一个全新的类型。像 Swift 中的其他类型,它们的名称(如 CompassPoint 和 Planet)应以大写字母开头。为列举类型提供单数而不是复数名称,因此它们就可以不言自明了:

 
var directionToHead = CompassPoint.West
 

当directonToHead与CompassPoint的一个可能值初始化时, directonToHead的类型即可推断。一旦directonToHead被声明为一个CompassPoint,您可以使用更短的点语法将其设置为不同的CompassPoint值:

 
directionToHead = .East
 

directionToHead的类型是已知的,所以你可以在设定它的值时删除该类型。在处理显式类型的枚举值时,可以用来编制高度可读的代码。

采用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的case,这段代码无法编译,因为它没有考虑CompassPoint成员的完整列表。要求竭力确保枚举成员不会偶然遗漏。

当为每一个枚举成员规定一个case不适当时,你可以提供一个default的案例以覆盖任何未被被明确处理的成员。

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

关联值

在上一节中的示例显示了枚举的成员是如何在自己的权利内定义(和类型)值的。你可以设置一个Planet. Earth常量或变量,随后检查这个值。但是,有时能够将其它类型的关联值 在这些成员值旁边存储是有用的。这使你能够将额外的自定义信息与成员值一起存储,并允许这些信息在你每次在你的代码中使用该成员时发生变化。

您可以定义Swift枚举以存储任何给定类型的关联值,如果需要,枚举的每个成员的值类型均可以改变。与此类似的枚举被称为可识别联合,标记联合,或在其他编程语言中称为变体。

例如,假设一个库存跟踪系统需要跟踪两种不同类型的条形码产品。有些产品上标有UPC -A格式的的一维条码,使用数字0到9,每一个条码均有一个“数字系统”的位,后跟十个“标识符”的位。这些后跟一个“检查”位以验证已正确扫描的代码:

barcode_UPC_2x.png

其他产品也标注有QR代码格式的二维条码,此类产品可使用任何ISO 8859-1字符,并且可对长达2953个字符的字符串进行编码:

barcode_QR_2x.png

便于库存跟踪系统能够将UPC-A条形码以三个整数的元组的形式进行存储,以及将QR代码条形码以任何长度的字符串进行存储。

在Swift内,可定义任何类型的产品条形码的枚举可能是这样的:

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

这可被解读为:

“定义一个枚举类型为Barcode,其可取含有类型(Int, Int, Int)关联值的UPCA的值,或者可取含有类型关联值的QRCode的值。 String'.”

此定义并没有规定任何Int或String的实际值-它只定义了关联值的类型,即Barcode的常量和变量等同于Barcode.UPCA 或Barcode.QRGod6时,可进行存储。

然后,可利用任何类型创建新条形码:

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

该例产生了一个称为productBarcode的新变量并赋予其含有一个关联元组值 (8, 8590951226, 3) 的Barcode.UPCA的值。所规定的“标识符”值在其整数值变量—85909—51226—内含有下划线,便于以条形码的形式阅读。

相同的产品可以被分配为一个不同类型的条形码:

 
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
 

此时,原Barcode.upcA及其整数值被新的Barcode.QRCode和其字符串值所替换。Barcode的常量和变量可对一个UPCA或一个QRCode(连同其关联值)进行存储,但是其只能在给定的时间内存储其中之一。

如上所述,可以通过执行switch语句检查不同的条码类型。但是,此时关联值可以作为switch语句的一部分提取。可提取每个关联值作为常量(以let为前缀)和变量(以var为前缀)以在switch事例块主体内部使用。

 
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."
 

原始值

关联值中的条形码实例说明了枚举成员是如何声明它们能够存储不同类型的关联值。枚举成员作为关联值的替代项,可以使用默认值(称为原始值)预先填充,此类值均为同一类型。

下述示例为将初始的ASCII值储存在命名的枚举成员旁:

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

此处,称为ASCIIControlCharacter的枚举的原始值被定义为类型Character,并且被设置为某些更常见的ASCII控制字符。Character以字符串和字符表述。

注,初始值与关联值不同。当你初次定义代码中的枚举时,如上所述的三个ASCII代码,原始值应设置为预先填充值。一个特定的枚举成员的初始值始终保持不变。当你根据其中一个枚举成员创建新的常量或变量时,此时可进行关联值设置,并且每次进行的此类设置可不同。

初始值可以是字符串、字符或任何整数或浮点型数值。在其枚举声明范围内,每个初始值必须是唯一的。当用整数定义原始值时,若没有为某些枚举成员指定值,此类原始值会自动增加。

下述为早期Planet枚举改进后的枚举,其原始的整数值表示每一个来自于sun的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值都能找到一个匹配的planet。正因为如此,该fromRaw类函数返回一个可选的枚举成员。在上述示例中,possiblePlanet为Planet类型或“可选的Planet”。

若你试图找到位置9上的Planet枚举类型,由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)")
prints "There isn't a planet at position 9"
昵    称:
验证码:

相关文档:

swift
IOS实例
ObjectiveC