从零开始Swift之枚举

枚举

枚举语法

enum SomeEnumeration {

}

eg 指南针上的四个主要的点

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

多种情况在一行中, 使用","分割

swift中约定俗成的枚举开头字母都是大写,而且不要使用复数形式

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

var directionToHead = CompassPoint.west

当使用CompassPoint的某个可能值初始化directionToHead时, 推断其类型, 一旦directionToHead声明为CompassPoint, 我们可以使用较短的.语法将其设置为不同的CompassPoint值

directionToHead = .south
directionToHead = .east
directionToHead = .south

在switch中使用枚举

directionToHead = .south
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")
}

原始值

枚举可以预填充默认值,成为原始值,他们都是相同类型, 原始值可以是字符串,字符或任何整数或浮点数类型。每个原始值在其枚举声明中必须是唯一的

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

隐式分配的原始值

当我们使用枚举存储整数或字符串原始值是, 不必为每种情况显式分配原始值. swift会自动分配值, 如果第一种情况没有设置值, 其值为0

下面的枚举是前面的Planet枚举的改进, 用整数原始值来表示每个行星的顺序

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

当使用字符串用原始值时, 每个案例的隐式值应该是该案例名称的文本.

将CompassPoint枚举改为原始值为字符串

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

可以使用rawValue属性访问枚举案例的原始值

let earthsOrder = Planet.earth.rawValue
// earthsOrder 的值为3

let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection的值为 "west"

从原始值初始化

如果使用原始值类型定义枚举, 则枚举会自动接收一个初始值, 改值包含原始值的类型(作为rawValue的参数), 并返回枚举或nil.我们可以使用初始化程序创建枚举的新实例

let possiblePlanet = Planet(rawValue: 7)
//possiblePlanet 的值为 uranus

如果你试图找到一个位置为11的行星,由原始值初始值器返回的可选Planet值将为nil:

let positionToFind = 11
if let somePlanet = Planet(rawValue: positionToFind) {
    switch somePlanet {
    case .earth:
        print("Mostly harmless")
    default:
        print("Not a safe place for humans")
    }
}else{
    print("There isn't planet at position \(positionToFind)")
}

递归枚举

递归枚举是枚举的另一个枚举实例作为一个或多个枚举case的关联值, 我们通过在其前面写入indirect指示枚举情况是递归的, 这告诉编译器插入必要的间接层.

enum ArithmeticExpression {
    case number(Int)
    indirect case
        addition(ArithmeticExpression, ArithmeticExpression)
    indirect case
        multiplication(ArithmeticExpression, ArithmeticExpression)
}

也可以将"indirect" 关键字写在"enum"前面

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}

这个枚举可以存储三种算术表达式:一个普通数,两个表达式的加法和两个表达式的乘法。 加法和乘法情况具有也是算术表达式的关联值 - 这些关联值使得可以嵌套表达式。 例如,表达式(5 + 4)* 2在乘法的右手侧具有数字,在乘法的左手侧具有另一表达式。 因为数据是嵌套的,用于存储数据的枚举还需要支持嵌套 - 这意味着枚举需要递归。 下面的代码显示为(5 + 4)* 2创建的ArithmeticExpression递归枚举:“

let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)

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

推荐阅读更多精彩内容

  • 本章将会介绍 闭包表达式尾随闭包值捕获闭包是引用类型逃逸闭包自动闭包枚举语法使用Switch语句匹配枚举值关联值原...
    寒桥阅读 516评论 0 2
  • 109.关联值 上部分实例展示枚举分支是一个定义值(类型值)。 你可以把一个常量或者变量设置成 Planet.ea...
    无沣阅读 442评论 0 3
  • 枚举为一组相关的值定义了一个共同的类型,使你可以在你的代码中以类型安全的方式来使用这些值。 如果你熟悉 C 语言,...
    雨影阅读 43评论 0 0
  • 枚举为一组相关的值定义了一个共同的类型,使得可以在代码中以类型安全的方式来使用这些值。 如果熟悉 C 语言,会知道...
    穷人家的孩纸阅读 399评论 1 4
  • 对文字,我已经疏懒到这个地步。好像已经忘记了发简书这回事。 现实中,有多少时间是拿来静静思考?我总是想把生活的常态...
    若水无心一阅读 261评论 8 23