Swift 枚举(enum)详解

作者: WSJay | 来源:发表于2018-08-08 10:46 被阅读0次

    Swift基础语法总结,来自苹果官方文档

    枚举(Enumeration)

    枚举在Swift中是 first-class types。与C,Objective-C中的枚举相比,Swift中枚举功能更强大。它支持很多只有类才有的特性,如: PropertiesMethodsInitializationExtensionsProtocols.

    1. 语法格式

    enum 枚举名{
        case
        case
        case
        ...
    }
    

    举例:

    //多个case分开写
    enum CompassPoint {
        case north
        case south
        case east
        case west
    }
    
    //多个case写在同一行,使用逗号分开
    enum Planet {
        case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
    }
    
    //创建CompassPoint的枚举实例
    var directionToHead = CompassPoint.west
    directionToHead = .east
    

    注意:与C和Objective-C不同,Swift枚举情况在创建时不分配默认整数值。在CompassPoint例子中,north,south,east和west不等于隐式0,1,2和3。

    2. Switch和Enumeration

    通常将单个枚举值与switch语句匹配:

    //switch覆盖CompassPoint的所有情况
    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")
    }
    // Prints "Watch out for penguins"
    
    
    //switch 没有覆盖Planet的所有情况,需要添加default
    let somePlanet = Planet.earth
    switch somePlanet {
    case .earth:
        print("Mostly harmless")
    default:
        print("Not a safe place for humans")
    }
    // Prints "Mostly harmless"
    
    

    注意:当switch没有覆盖枚举中所有case时,需要添加default,来处理其他情况!

    3.迭代枚举

    当需要迭代枚举中的所有情况时,需要自定义的枚举遵守CaseIterable协议

    enum Beverage: CaseIterable {
        case coffee, tea, juice
    }
    let numberOfChoices = Beverage.allCases.count
    print("\(numberOfChoices) beverages available")
    // Prints "3 beverages available"
    
    
    for beverage in Beverage.allCases {
        print(beverage)
    }
    // coffee
    // tea
    // juice
    

    4.关联值(Associated Values)

    我们可以定义Swift枚举来存储任何给定类型的关联值,而且每种枚举情况的值类型可以不同。

    enum Barcode {
        case upc(Int, Int, Int, Int)
        case qrCode(String)
    }
    
    //创建Barcode枚举实例
    var productBarcode = Barcode.upc(8, 85909, 51226, 3)
    productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
    

    可以将关联值提取为switch语句的一部分。将每个关联值提取为常量(let)或变量(var),以便在switch中处理:

    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).")
    }
    // Prints "QR code: ABCDEFGHIJKLMNOP."
    

    如果枚举case的所有关联值都被提取为常量,或者都被提取为变量,则可以将var或let放置在case名称前面,来提取所有的关联值:

    switch productBarcode {
    case let .upc(numberSystem, manufacturer, product, check):
        print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
    case let .qrCode(productCode):
        print("QR code: \(productCode).")
    }
    // Prints "QR code: ABCDEFGHIJKLMNOP."
    

    5.原始值(Raw Values)

    关联值 ”表明了枚举如何存储不同类型的关联值。作为关联值的替代,枚举情况可以预先设置默认值(称原始值),它们都是相同的类型。
    原始值可以是字符串,字符,整数或浮点数类型。每个原始值在其枚举声明中必须是唯一的。

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

    注意:原始值是不一样的关联值。当您首次在代码中定义枚举时,原始值将设置为预填充值,如上面的三个ASCII代码。特定枚举情况的原始值始终相同。根据枚举的情况创建新常量或变量时,将设置关联值,每次执行此操作时可能会有所不同。

    (1). 隐式分配原始值

    当使用存储整数或字符串原始值的枚举时,不必为每种case显式分配原始值,Swift将自动为其分配值。如果使用整数为原始值,则每个case的原始值依次自增1。若第一个case没有设置原始值,则默认为0:

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

    当使用字符串作为原始值时,每个case的隐含值是该case的名称。

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

    使用枚举的rawValue属性来访问其原始值:

    let earthsOrder = Planet.earth.rawValue
    // earthsOrder is 3
    
    let sunsetDirection = CompassPoint.west.rawValue
    // sunsetDirection is "west"
    
    (2).使用原始值初始化枚举实例

    如果使用原始值类型定义枚举,则枚举会自动接收一个带有原始值的初始化器,并返回可选类型的枚举实例。

    let possiblePlanet = Planet(rawValue: 7)
    
    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 a planet at position \(positionToFind)")
    }
    // Prints "There isn't a planet at position 11"
    

    注意:原始值初始化器是一个可用的初始化器,因为并非每个原始值都将返回枚举情况。Failable Initializers

    6.递归枚举

    递归枚举是将枚举的另一个实例作为一个或多个枚举case的关联值。在枚举case 前面添加关键字indirect来指明该枚举case是递归的,这就告诉了编译器插入必要的间接层。
    例如,下面是存储简单算术表达式的枚举:

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

    还可以在枚举enum之前添加indirect,以便为所有具有关联值的枚举case启用间接:

    indirect enum ArithmeticExpression {
        case number(Int)
        case addition(ArithmeticExpression, ArithmeticExpression)
        case multiplication(ArithmeticExpression, 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))
    // Prints "18"
    

    7.其他专题模块

    Swift 4.2 基础专题详解

    相关文章

      网友评论

        本文标题:Swift 枚举(enum)详解

        本文链接:https://www.haomeiwen.com/subject/vglgvftx.html