枚举语法那一小节的例子演示了如何定义和分类枚举的成员。你可以为 Planet.earth
设置一个常量或者变量,并在赋值之后查看这个值。然而,有时候把其他类型的值和成员值一起存储起来会很有用。这额外的信息称为关联值,并且你每次在代码中使用该枚举成员时,还可以修改这个关联值。
你可以定义 Swift 枚举来存储任意类型的关联值,如果需要的话,每个枚举成员的关联值类型可以各不相同。枚举的这种特性跟其他语言中的可识别联合(discriminated unions),标签联合(tagged unions),或者变体(variants)相似。
例如,假设一个库存跟踪系统需要利用两种不同类型的条形码来跟踪商品。有些商品上标有使用 0
到 9
的数字的 UPC 格式的一维条形码。每一个条形码都有一个代表数字系统的数字,该数字后接五位代表厂商代码的数字,接下来是五位代表“产品代码”的数字。最后一个数字是检查位,用来验证代码是否被正确扫描:
其他商品上标有 QR 码格式的二维码,它可以使用任何 ISO 8859-1 字符,并且可以编码一个最多拥有 2,953 个字符的字符串:
这便于库存跟踪系统用包含四个整型值的元组存储 UPC 码,以及用任意长度的字符串储存 QR 码。
在 Swift 中,使用如下方式定义表示两种商品条形码的枚举:
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
以上代码可以这么理解:“定义一个名为 Barcode
的枚举类型,它的一个成员值是具有 (Int,Int,Int,Int)
类型关联值的 upc
,另一个成员值是具有 String
类型关联值的 qrCode
。”
这个定义不提供任何 Int
或 String
类型的关联值,它只是定义了,当 Barcode
常量和变量等于 Barcode.upc
或 Barcode.qrCode
时,可以存储的关联值的类型。
然后你可以使用任意一种条形码类型创建新的条形码,例如:
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
上面的例子创建了一个名为 productBarcode
的变量,并将 Barcode.upc
赋值给它,关联的元组值为 (8, 85909, 51226, 3)
。
同一个商品可以被分配一个不同类型的条形码,例如:
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
这时,原始的 Barcode.upc
和其整数关联值被新的 Barcode.qrCode
和其字符串关联值所替代。Barcode
类型的常量和变量可以存储一个 .upc
或者一个 .qrCode
(连同它们的关联值),但是在同一时间只能存储这两个值中的一个。
你可以使用一个 switch 语句来检查不同的条形码类型,和之前使用 Switch 语句来匹配枚举值的例子一样。然而,这一次,关联值可以被提取出来作为 switch 语句的一部分。你可以在 switch
的 case 分支代码中提取每个关联值作为一个常量(用 let
前缀)或者作为一个变量(用 var
前缀)来使用:
switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
print("QR code: \(productCode).")
}
// 打印“QR code: ABCDEFGHIJKLMNOP.”
如果一个枚举成员的所有关联值都被提取为常量,或者都被提取为变量,为了简洁,你可以只在成员名称前标注一个 let
或者 var
:
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
print("QR code: \(productCode).")
}
// 打印“QR code: ABCDEFGHIJKLMNOP.”