当前位置: 首页 > 工具软件 > Swift-T > 使用案例 >

➽Swift-07枚举

萧修永
2023-12-01

枚举语法

enum SomeEnumeration {
    // enumeration definition goes here
}
enum CompassPoint {
    case north
    case south
    case east
    case west
}
enum Planet {
    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
var directionToHead = CompassPoint.west

一旦将directionToHead声明为CompassPoint后,可以使用较短的点语法将其设置为不同的CompassPoint值:

directionToHead = .east

switch语句中匹配枚举值

directionToHead = .south
switch directionToHead {
case .north:
    print("Lots of planets have a north")
case .south:
    print("Watch out for penguins")// printed
case .east:
    print("Where the sun rises")
case .west:
    print("Where the skies are blue")
}

迭代枚举值
对于某些枚举,收集该枚举的所有case非常有用。您可以通过在枚举名称后写入:CaseIterable来启用此功能。Swift将所有case的集合公开为枚举类型的allCases属性。下面是一个例子:

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

关联值

enum Barcode {
	case upc(Int, Int, Int, Int)// 条形码
	case qrCode(String)// 二维码
}
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
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注释:

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

原始值(Raw Values)
下面是一个将原始ASCII值与命名枚举case一起存储的示例:

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

这里,称为ASCIIControlCharacter的枚举的原始值被定义为Character类型,并被设置为一些更常见的ASCII控制字符。

原始值可以是字符串、字符或任何整数或浮点数类型。每个原始值在其枚举声明中必须是唯一的。

原始值与关联值不同。当您第一次在代码中定义枚举时,原始值被设置为预填充值,就像上面的三个ASCII代码一样。特定枚举case的原始值始终相同。关联值是在基于枚举的一种情况创建新常量或变量时设置的,每次创建时可以不同。

隐式指定原始值
当整数用于原始值时,每种情况的隐式值都比前一种情况多一个。如果第一个case没有设置值,则其值为0。

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

以上Planet.mercury的显式原始值为1,Planet.venus的隐式原始值为2,依此类推。

当字符串用于原始值时,每个case的隐式值都是该case名称的文本。

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

以上CompassPoint.south有一个隐含的原始值"south",以此类推。

可以使用枚举case的rawValue属性访问其原始值:

let earthsOrder = Planet.earth.rawValue
// earthsOrder is 3

let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection is "west"

从原始值初始化

let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet is of type Planet? and equals Planet.uranus

然而,并非所有可能的Int值都能找到匹配的行星。因此,原始值初始值设定项总是返回可选的枚举case。在上面的示例中,possiblePlanet的类型为Planet?,或“可选的Planet”。

如果尝试查找位置为11的行星,则原始值初始值设定项返回的可选行星值将为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 a planet at position \(positionToFind)")
}
// Prints "There isn't a planet at position 11"

如果let somePlanet=Planet(rawValue: 11)创建一个可选Planet,并将somePlanet设置为该可选Planet的值(如果可以检索)。在本例中,无法检索位置为11的Planet,因此将执行else分支。

递归枚举
递归枚举是将枚举的另一个实例作为一个或多个枚举case的关联值的枚举。您可以通过在枚举case之前写入indirect来指示枚举case是递归的,这会告诉编译器插入必要的间接层。

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

还可以在枚举开始之前写入indirect,以便为所有具有关联值的枚举case启用间接寻址:

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

此枚举可以存储三种算术表达式:普通数、两个表达式的加法和两个表达式的乘法。加法(addition)和乘法(multiplication) case都有相关的值,这些值也是算术表达式。这些相关的值使嵌套表达式成为可能。例如,表达式(5+4)*2在乘法的右侧有一个数字,在乘法的左侧有另一个表达式。因为数据是嵌套的,所以用于存储数据的枚举也需要支持嵌套,这意味着枚举需要是递归的。下面的代码显示为(5+4)*2创建的算术表达式递归枚举:

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"
 类似资料: