8.枚举
枚举为一组相关的值定义了一个共同的类型,使你可以在你的代码中以类型安全的方式来使用这些值。Swift 中的枚举更加灵活,不必给每一个枚举成员提供一个值。如果给枚举成员提供一个值(称为“原始”值),则该值的类型可以是字符串,字符,或是一个整型值或浮点数。
1.枚举语法
enum SomeEnumeration { // 枚举定义放在这里 }
示例:
enum CompassPoint { case North; case South; case East; case West; }; //多个成员值在同一行 enum CompassPoint2 { case North, South, East, West; }; var directionToHead : CompassPoint = .West; //【说明】: //1.使用case关键字来定义一个新的枚举成员值。 //2.Swift 的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的例子中,North,South,East和West不会被隐式地赋值为0,1,2和3。相反,这些枚举成员本身就是完备的值,这些值的类型是已经明确定义好的CompassPoint类型。 //3.多个成员值可以出现在同一行上,用逗号隔开。 //4.当枚举类型已知时,为其赋值可以省略枚举类型名。
2.使用 Switch 语句匹配枚举值
enum CompassPoint { case North, South, East, West; }; var directionToHead : CompassPoint = .West; switch directionToHead { case .North: print("Lots of planets have a north"); case .South: print("Watch out for penguins"); case .East: print("Where the sun rises"); case .West: print("Where the skies are blue"); }
3.关联值
enum Barcode { case UPCA(numberSystem: Int, manufacturer: Int, product: Int, check: Int); case QRCode(productCode: String); } var productBarcode = Barcode.UPCA(numberSystem: 8, manufacturer: 85909, product: 51226, check: 3); // productBarcode = .QRCode(productCode: "GofLee"); switch productBarcode { case .UPCA(let numberSystem, let manufacturer, let product, let check): //关联值作为常量 print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check)."); case .QRCode(var productCode): //关联值作为变量 print("QR code: \(productCode).") } //【说明】:Barcode类型的常量和变量可以存储一个.UPCA或者一个.QRCode(连同它们的关联值),但是在同一时间只能存储这两个值中的一个。
4.原始值
enum ASCIIControlCharacter: Character { case Tab = "\t"; case LineFeed = "\n"; case CarriageReturn = "\r"; } //【说明】: //1.原始值(默认值)的类型必须相同,并且是必须显示指定; //2.对于一个特定的枚举成员,它的原始值始终不变。关联值是创建一个基于枚举成员的常量或变量时才设置的值,枚举成员的关联值可以变化。 //进化1:在使用原始值为整数或者字符串类型的枚举时,不需要显式地为每一个枚举成员设置原始值,Swift 将会自动赋值。 enum Planet: Int { case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune } enum Seasons: String { case Spring, Summer, Autumn, Winter } //【说明】:Planet.Venus的隐式原始值为2;Seasons.Summer的隐式原始值Summer。 // TODO: 使用示例:使用原始值初始化枚举实例 let possiblePlanet = Planet(rawValue: 7); //【说明】:如果在定义枚举类型的时候使用了原始值,那么将会自动获得一个初始化方法,这个方法接收一个叫做rawValue的参数,参数类型即为原始值类型,返回值则是枚举成员或nil。
5.递归枚举
- 递归枚举(recursive enumeration)是一种枚举类型,它有一个或多个枚举成员使用该枚举类型的实例作为关联值。使用递归枚举时,编译器会插入一个间接层。你可以在枚举成员前加上indirect来表示该成员可递归。
enum ArithmeticExpression { case Number(value: Int); indirect case Addition(expressionOne: ArithmeticExpression, expressionTwo: ArithmeticExpression); indirect case Multiplication(expressionOne: ArithmeticExpression, expressionTwo: ArithmeticExpression); } func evaluate(expression: ArithmeticExpression) -> Int { switch expression { case .Number(let value): return value; case .Addition(let left, let right): return evaluate(left) + evaluate(right) case .Multiplication(let left, let right): return evaluate(left) * evaluate(right) } } // 计算 (5 + 4) * 2 let five = ArithmeticExpression.Number(value: 5); let four = ArithmeticExpression.Number(value: 4); let sum = ArithmeticExpression.Addition(expressionOne: five, expressionTwo: four); let product = ArithmeticExpression.Multiplication(expressionOne: sum, expressionTwo: ArithmeticExpression.Number(value: 2)); print(evaluate(product)); // 输出 "18"
无善无恶心之体,
有善有恶意之动,
知善知恶是良知,
为善去恶是格物。