注:本文为自己学习The Swift Programming Language的笔记,其中的例子为引用原书和其他博文或自己原创的。每个例子都会批注一些实践过程中的经验或思考总结。
1.基础
枚举类型定义了一组通用类型的相关联的值,它提供一种类型安全的方式来使用这些值。
Swift的美剧类型比C语言的枚举类型更加灵活,它并不需要为每个枚举成员赋一个值;如果赋了值,这个值可以是字符串、字符以及整数和浮点数的任何类型,它被称作原始值[raw value]。
除此之外,枚举成员可以可以制定任何类型的相关值储存在不同的成员值中,很像其他语言的联合体[Union]和变体[Variant]。你可以定义一组通用的相关成员作为枚举的一部分,每一组都有不同的一组与它相关的适当类型的数值。
Swift的枚举类型是一等类型(此外类和结构体也属于一等类型),它们采用了很多传统上只被类所支持的特征,比如说计算属性(用于提供关于枚举当前值的附加信息)、实例方法(用于提供和枚举所代表的值相关联的功能)。
枚举也可以定义构造函数来提供一个初始成员值,可以被扩展,可以遵守协议来提供标准的功能。
2.枚举语法
枚举用enum关键字来声明,与C语言不同的是每一个枚举成员需要用case关键字引出:
enum CompassPoint {
case North
case South
case East
case West
}
不像类C语言,Swift的枚举成员在创建时是没有整型默认值的。比如上例中North并不隐式的等于0。不同的枚举成员可以显式定义不同类型。
不同的枚举成员可以写在同一个case中:
enum Planet {
case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
Swift中每个枚举类型,比如CompassPoint或者Planet都是一个全新的类型,它的首字母应该写成大写而且是单数形式。
用点运算符引出枚举成员,一旦一个变量被声明为某种枚举类型变量,那么可以省略枚举名字直接用点符号和枚举成员赋值:
var direction = CompassPoint.North
direction = .South
3.switch语句匹配枚举值
我们常用case来判断枚举变量的值,然后做出相应的响应:
direction = .South
switch direction {
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
由于类型推断case中枚举类型可以省略,并且由于switch语句要求完全枚举,因此若不将枚举成员一一列举就要加上default语句。
4.关联值
有时候把一些和枚举成员相关联的不同类型的值储存在枚举成员后面会很有用,它能配合枚举成员存储额外的信息。
Swift的关联值[Associated Values]可以是任意的已知类型,每个枚举成员也可以有不同类型的关联值。
用原书中比较形象的例子来说明关联值的使用方法。
库存追踪系统需要追踪两种不同类型的条码。比如一维条码(条形码),有些产品使用UPC-A格式的条形码,它使用0-9的数字,首位为数字系统编码,中间10位为标识号码,最后一位是检查是否正确扫描的检错码。而有些产品又使用二位条码(二维码),QR格式的二维码可以使用任意的ISO 8859-1字符,并且能被最多2953个字符的字符串编码。所以表示一个库存追踪系统最方便的形式是在UPCA条码后添加三元Int元组关联值和在QRCode条码后添加String类型关联值:
enum Barcode {
case UPCA(Int, Int, Int)
case QRCode(String)
}
枚举成员定义时不给出关联值具体值,而是在定义枚举类型常量或变量是给出,它表示该枚举成员的额外信息:
var productBarcode = Barcode.UPCA(8, 85909_51226, 3)
在匹配含有关联值的枚举变量或常量是可以使用case值绑定的形式的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).")
}
如果一个枚举成员的所有值绑定都是常量或变量的一类时,let或var可以提出括号书写,上面的代码等价于:
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).")
}
5.原始值
enum PlanetWithRawValue : Int {
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
上例中,自动原始值让PlanetWithRawValue.Earth = 3。