Swift enum

在 swift 当中,enum 是一等类型。他们采用了很多在传统上只被类所支持的特性。例如计算属性、实例方法。enum 也可以用于定义构造函数提供一个初始值,也可以在原始实现的基础上扩展他们的功能。还可以遵循协议来提供标准的功能。用 enum 表示枚举:

1
2
3
4
5
6
enum CompassPoint {
case north
case south
case east
case west
}

关联值

有时候将其他类型的关联值和成员值一起存储起来,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}

// 变量 productBarcode 关联的元组值为(8, 85909, 51226, 3)
var productBarcode = Barcode.upc(8, 85909, 51226, 3)

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

原始值

枚举成员可以被默认值(称为原始值)填充,这些原始值的类型必须相同

1
2
3
4
5
enum ASCIIControlCharacter: Character {
case tab = "\t"
case lineFeed = "\n"
case carriageReturn = "\r"
}

在使用整数作为原始值时,原始值会隐式赋值的值依次递增 1:

1
2
3
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

使用字符串作为枚举类型的原始值时,原始值默认是就该枚举类型的值:

1
2
3
enum CompassPoint: String {
case north, south, east, west
}

使用该枚举成员rawValue可访问该枚举成员的原始值:

1
2
let earthsOrder = Planet.earth.rawValue // 3
let sunsetDirection = CompassPoint.west.rawValue // "west"

在定义枚举的时候,会自动获得初始化方法,即可以自动创建一个枚举实例:

1
2
let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet 类型为 Planet? 值为 Planet.uranus

递归枚举

递归枚举:递归枚举是一种枚举类型,它有一个或多个枚举成员使用该枚举类型的实例作为关联值。使用递归枚举时,编译
器会插入一个间接层。你可以在枚举成员前加上 indirect 来表示该成员可递归。这里使用官方文档中的计算表达式(5 + 4) * 2的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}

// 需要注意这里并不是真正计算表达式(5 + 4) * 2,而是把 five 和 four 作为枚举值的相关值再次创建枚举,然后复制给 sum 和 product
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
// 这里就表示了表达式 (5 + 4) * 2。类型为 ArithmeticExpression
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))

// 计算表达式求值函数
func evaluate(_ expression: ArithmeticExpression) -> Int {
switch expression {
case let .number(value):
return value
case let .addition(left, right):
return evaluate(left) + evaluate(right)
case let .multiplication(left, right):
return evaluate(left) * evaluate(right)
}
}

print(evaluate(product)) // 18

另外,也可以再枚举类型开头加上indirect关键字来表明它的所有成员都是可递归的:

1
2
3
4
5
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}