Swift4.2语言规范(十) 枚举
一个枚举定义了一个通用型的一组相关的值,使你在你的代码中的一个类型安全的方式这些值来工作。 如果您熟悉C,您将知道C枚举将相关名称分配给一组整数值。Swift中的枚举更加灵活,并且不必为枚举的每个案例提供值。如果一个值(被称为“原始”的值)被提供给每个枚举的情况下,该值可以是一个字符串,一个字符,或任何整数的值或者浮点型。 或者,枚举情况可以指定要与每个不同的案例值一起存储的任何类型的关联值,就像其他语言中的联合或变体一样。您可以将一组通用的相关案例定义为一个枚举的一部分,每个枚举都有一组与之关联的适当类型的不同值。 Swift中的枚举本身就是一流的类型。它们采用传统上仅由类支持的许多功能,例如计算属性以提供有关枚举当前值的其他信息,以及实例方法以提供与枚举所代表的值相关的功能。枚举还可以定义初始化器以提供初始案例值;?可以扩展以扩展其原始实现之外的功能;?并且可以符合协议以提供标准功能。 有关这些功能的更多信息,请参阅属性,方法,初始化,扩展和协议。 枚举语法您将使用 1 enum SomeEnumeration { 2 // enumeration definition goes here 3 } 以下是指南针的四个要点的示例: 1 enum CompassPoint { 2 case north 3 case south 4 case east 5 case west 6 } 在枚举定义的值(例如 注意 与C和Objective-C不同,Swift枚举情况在创建时未分配默认整数值。在 多个案例可以出现在一行中,以逗号分隔: 1 enum Planet { 2 case mercury,venus,earth,mars,jupiter,saturn,uranus,neptune 3 } 每个枚举定义都定义了一个新类型。与Swift中的其他类型一样,它们的名称(例如 var directionToHead = CompassPoint.west
directionToHead = .east 类型 使用Switch语句匹配枚举值您可以将单个枚举值与 1 directionToHead = .south 2 switch directionToHead { 3 case .north: 4 print("Lots of planets have a north") 5 case .south: 6 print("Watch out for penguins") 7 case .east: 8 print("Where the sun rises") 9 case .west: 10 print("Where the skies are blue") 11 } 12 // Prints "Watch out for penguins" 您可以将此代码读作: “依据值 …等等。 如控制流程中所述, 如果不适合 1 let somePlanet = Planet.earth 2 switch somePlanet { 3 case .earth: 4 print("Mostly harmless") 5 default: 6 print("Not a safe place for humans") 7 } 8 // Prints "Mostly harmless" 迭代枚举案例对于某些枚举,拥有所有枚举的案例集合很有用。您可以通过在枚举名称后面写入来启用它。Swift将所有案例的集合公开为枚举类型的属性。这是一个例子: 1 enum Beverage: CaseIterable { 2 case coffee,tea,juice 3 } 4 let numberOfChoices = Beverage.allCases.count 5 print("(numberOfChoices) beverages available") 6 // Prints "3 beverages available" 在上面的示例中,您编写 1 for beverage in Beverage.allCases { 2 print(beverage) 3 } 4 // coffee 5 // tea 6 // juice ? 上面示例中使用的语法将枚举标记为符合 关联值上一节中的示例显示了枚举的情况本身是如何定义(和类型化)的值。您可以将常量或变量设置为 您可以定义Swift枚举以存储任何给定类型的关联值,并且如果需要,每种枚举情况的值类型可以不同。与这些类似的枚举称为区别联合,标记联合或其他编程语言中的变体。 例如,假设库存跟踪系统需要通过两种不同类型的条形码跟踪产品。有些产品标有UPC格式的1D条形码,使用数字 其他产品使用QR码格式的二维条码进行标记,可以使用任何ISO 8859-1字符,并且可以编码长达2,953个字符的字符串: 对于库存跟踪系统来说,能够将UPC条形码存储为四个整数的元组以及QR码条形码作为任意长度的字符串将是方便的。 在Swift中,定义任一类型的产品条形码的枚举可能如下所示: 1 enum Barcode { 2 case upc(Int,Int,Int) 3 case qrCode(String) 4 } 这可以理解为: “定义枚举类型 此定义不提供任何实际值 然后可以使用以下任一类型创建新的条形码: var productBarcode = Barcode.upc(8,85909,51226,3) 此示例创建一个名为的新变量, 可以为同一产品分配不同类型的条形码: productBarcode = .qrCode("ABCDEFGHIJKLMNOP") 此时,原始 与以前一样,可以使用switch语句检查不同的条形码类型。但是,这次可以将关联值提取为switch语句的一部分。您将每个关联值提取为常量(带 1 switch productBarcode { 2 case .upc(let numberSystem,let manufacturer,let product,let check): 3 print("UPC: (numberSystem),(manufacturer),(product),(check).") 4 case .qrCode(let productCode): 5 print("QR code: (productCode).") 6 } 7 // Prints "QR code: ABCDEFGHIJKLMNOP." 如果枚举案例的所有关联值都被提取为常量,或者如果所有这些值都被提取为变量,则可以在案例名称前面放置单个 1 switch productBarcode { 2 case let .upc(numberSystem,manufacturer,product,check): 3 print("UPC : (numberSystem),(check).") 4 case let .qrCode(productCode): 5 print("QR code: (productCode).") 6 } 7 // Prints "QR code: ABCDEFGHIJKLMNOP." 默认值“?关联值?”中的条形码示例显示了枚举的情况如何声明它们存储了不同类型的关联值。作为关联值的替代,枚举情况可以预先填充默认值(称为原始值),它们都是相同的类型。 这是一个存储原始ASCII值和命名枚举情况的示例: 1 enum ASCIIControlCharacter: Character { 2 case tab = "t" 3 case lineFeed = "n" 4 case carriageReturn = "r" 5 } 这里,被调用枚举的原始值 原始值可以是字符串,字符或任何整数或浮点数类型。每个原始值在其枚举声明中必须是唯一的。 注意 原始值是不一样的关联值。当您首次在代码中定义枚举时,原始值将设置为预填充值,如上面的三个ASCII代码。特定枚举情况的原始值始终相同。根据枚举的情况创建新常量或变量时,将设置关联值,每次执行此操作时可能会有所不同。 隐含地分配默认值当您使用存储整数或字符串原始值的枚举时,您不必为每个案例显式分配原始值。如果不这样做,Swift将自动为您分配值。 例如,当整数用于原始值时,每个案例的隐含值比前一个案例多一个。如果第一种情况没有设置值,则其值为 下面的枚举是先前 1 enum Planet: Int { 2 case mercury = 1,neptune 3 } 在上面的示例中, 当字符串用于原始值时,每个案例的隐含值是该案例名称的文本。 下面的枚举是前面 1 enum CompassPoint: String { 2 case north,south,east,west 3 } 在上面的示例中, 您可以使用其 1 let earthsOrder = Planet.earth.rawValue 2 // earthsOrder is 3 3 4 let sunsetDirection = CompassPoint.west.rawValue 5 // sunsetDirection is "west" 默认值初始化如果使用默认值类型定义枚举,则枚举会自动接收一个初始值设定项,该初始值设定项接受默认值类型的值(作为参数调用 这个例子从原始值中识别天王星 1 let possiblePlanet = Planet(rawValue: 7) 2 // possiblePlanet is of type Planet? and equals Planet.uranus 然而,并非所有可能的 注意 原始值初始化程序是一个可用的初始化程序,因为并非每个原始值都将返回枚举情况。有关更多信息,请参阅Failable Initializers。 如果您尝试查找位置为的行星,则原始值初始值设定项返回 1 let positionToFind = 11 2 if let somePlanet = Planet(rawValue: positionToFind) { 3 switch somePlanet { 4 case .earth: 5 print("Mostly harmless") 6 default: 7 print("Not a safe place for humans") 8 } 9 } else { 10 print("There isn‘t a planet at position (positionToFind)") 11 } 12 // Prints "There isn‘t a planet at position 11" 此示例使用可选绑定尝试访问原始值为的行星 if let somePlanet = Planet(rawValue: 11)PlanetsomePlanetPlanet11else 递归枚举递归枚举是具有枚举作为一个或一个以上的枚举案件相关联的值的另一个实例的枚举。您通过 例如,这是一个存储简单算术表达式的枚举: 1 enum ArithmeticExpression { 2 case number(Int) 3 indirect case addition(ArithmeticExpression,ArithmeticExpression) 4 indirect case multiplication(ArithmeticExpression,ArithmeticExpression) 5 } 您还可以 1 indirect enum ArithmeticExpression { 2 case number(Int) 3 case addition(ArithmeticExpression,ArithmeticExpression) 4 case multiplication(ArithmeticExpression,ArithmeticExpression) 5 } 此枚举可以存储三种算术表达式:普通数字,两个表达式的相加以及两个表达式的相乘。将 1 let five = ArithmeticExpression.number(5) 2 let four = ArithmeticExpression.number(4) 3 let sum = ArithmeticExpression.addition(five,four) 4 let product = ArithmeticExpression.multiplication(sum,ArithmeticExpression.number(2)) 递归函数是处理具有递归结构的数据的简单方法。例如,这是一个计算算术表达式的函数: 1 func evaluate(_ expression: ArithmeticExpression) -> Int { 2 switch expression { 3 case let .number(value): 4 return value 5 case let .addition(left,right): 6 return evaluate(left) + evaluate(right) 7 case let .multiplication(left,right): 8 return evaluate(left) * evaluate(right) 9 } 10 } 11 12 print(evaluate(product)) 13 // Prints "18" 此函数只需返回相关值即可评估普通数字。它通过评估左侧的表达式,评估右侧的表达式,然后将它们相加或相乘来评估加法或乘法。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |