Swift3.0枚举(Enumerations)

枚举是啥我就不多说了。
Swift中的枚举更灵活,并且不必给每个枚举成员赋值。如果给枚举成员赋值(称为『原始』值),这个值可以是字符串、字符、整型或者浮点型。

此外,枚举成员可以指定任意类型的关联值存储到枚举成员中,就像其他语言中的联合体(unions)和变体(variants)。每一个枚举成员都可以有适当类型的关联值。

在 Swift 中,枚举类型是一等(first-class)类型。它们采用了很多在传统上只被类(class)所支持的特性,例如计算型属性(computed properties),用于提供枚举值的附加信息,实例方法(instance methods),用于提供和枚举值相关联的功能。枚举也可以定义构造函数(initializers)来提供一个初始值;可以在原始实现的基础上扩展它们的功能;还可以遵守协议(protocols)来提供标准的功能。

原谅上面这两段话,我是copy的。。

枚举语法(Enumeration Syntax)

先来个简单的枚举:

enum CompassPoint {
    case north
    case south
    case east
    case west
}

注意
与C和OC不同,Swift的枚举在创建的时候是不会赋一个默认的整型值的。相反,在上面的例子中,枚举的每个成员的值就他们本身,并且类型就是 CompassPoint 类型。

多个成员出现在一行的时候,用逗号隔开:

enum Planet {
    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}

每个枚举都是一个新的类型,所以和Swift中的其他类型一样,首字母大写。并且最好用单数名字而不是复数名字:

var directionToHead = CompassPoint.north

上面🌰中,directionToHead被推断为CompassPoint类型,所以当你在改变值的时候可以使用更简短的点语法:

directionToHead = .south

用Swift语句匹配枚举值(Matching Enumeration Values with a Switch Statement)

Matching Enumeration Values with a Switch Statement🌰

关联值(Associated Values)

在Swift的枚举中,可以给每个枚举成员设置关联值,各个成员之间的关联值的类型可以不相同,并且在使用的时候可以修改关联值。枚举的这种特性跟其他语言中的可识别联合(discriminated unions),标签联合(tagged unions),或者变体(variants)相似。

举个🌰,现在有一个厂商,它有两种条形码。一种是UPC-A格式的一维码,是由四个部分组成的:『数字系统』(1位)、『厂商代码』(5位)、『产品代码』(5位)、『检查位』(1位):


一维码

另一种就是 QR 码格式的二维码,可以存储最多 2953个字符的字符串:


二维码

所以这个枚举就可以这么定义:

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrcode(String)
}

这样定义了之后不会赋任何值,只是声明了类型。但是当Barcode
常量和变量等于 Barcode.UPCA 或 Barcode.QRCode 时,可以存储的关联值的类型:

var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrcode("ABCDEFGHIJKLMNOP")

这样的情况下,productBarcode的值就会被后面的这个替换掉。


🌰

如果每个关联值都被提取成常亮(变量),为了简洁,只需要在成员名称前面标注 let(var) 就可以了:


还是那个🌰

原始值(Raw Values)

上面的🌰讲了一下怎么关联不同的值,接下来要说的就是怎么设置默认值(原始值),但是设置原始值,每个成员的类型必须一致:

enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}

原始值可以是字符串、字符,也可以是任意值的整型或浮点型,但是每个成员的值必须是唯一的!

注意
原始值和关联值是不同的。原始值就是枚举定义时预先填充的值,而关联值是一个基于枚举类型的常量(变量)才设置的值。最显著的区别就是原始值设置之后就不会改变了,但是关联值是会在之后的调用中改变的。

原始值的隐式赋值(Implicitly Assigned Raw Values)
当设置用字符串和整型设置原始值的时候,不必给每一个成员都设置一遍,Swift会自动设置。

举个🌰,当设置整型的时候,隐式赋值的值会一次增加1,如果第一个枚举成员没有设置原始值,其原始值为0:

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

当设置的是字符串的时候,隐式赋值就是没给成员的名字:


总结一下

用原始值初始化枚举实例(Initializing from a Raw Value)

文字没整理好怎么翻译,直接上🌰:


🌰

这个🌰中不是所有的rawValue都可以找到一个对应的枚举成员,也就是说用这种方法创建的枚举实例返回的类型是一个可选类型。再通俗点就是这么初始化实例有可能返回nil:


不一样的🌰

递归枚举(Recursive Enumerations)

递归枚举也是枚举的一个类型,它是由一个或者多个枚举成员使用该枚举类型的实例作为关联值。在枚举成员前加上 indirect 关键字来表示该成员可递归,同时告诉编译器插入一个间接层(layer of indirection):


举个小🌰

也可以在枚举前面加上 indirect 来表明所有的成员都是可以递归的:


🌰

下面的🌰展示了使用ArithmeticExpression这个递归枚举计算表达式(5 + 4) * 2:


怎么感觉这个🌰让我写有点困难呢

推荐阅读更多精彩内容