swift之枚举

最后更新于:2022-04-01 11:39:51

在C语言中枚举名和一个整型值相对应 Swift中的枚举更加灵活,不必给每⼀个枚举成员提供⼀个值。如果给枚举成员提供⼀个值(称为“原始”值),则该值的类型可以是字符串,字符,或是⼀个整型值或浮点数。 此外,枚举成员可以指定任何类型的相关值存储到枚举成员值中,就像其他语⾔中的联合体(unions)和变体(variants)。你可以定义⼀组通⽤的相关成员作为枚举的⼀部分,每⼀组都有不同的⼀组与它相关的适当类型的数值。 1、枚举语法 使⽤ enum  关键词来创建枚举并且把它们的整个定义放在⼀对⼤括号内: ~~~ enum SomeEnumeration { // enumeration definition goes here } ~~~ ~~~ enum CompassPoint { case North case South case East case West } // North,South,East 和 West 不会隐式地赋值为了 0 , 1 , 2 和 3 print(CompassPoint.North) //North //多个成员值可以在同一行上,用逗号隔开 enum T1 { case T11, T12, T13, T14 } print("\(T1.T11), \(T1.T12)") //T11, T12 //每个枚举定义了一个全新的类型,他们的名字必须以大写字母开头 var t2 = T1.T12 //t2的类型可以被推断出来 let t1 : T1 = .T13 //定义一个变量或常量为枚举类型的时候,如果指定了变量的枚举类型,可以使用如上所示的缩写语法 t2 = .T13 //当t2的类型已知的时候,也可以省略枚举名 ~~~ 2、匹配枚举值和switch语句 ~~~ enum Test1 { case TestValue1, TestValue2, TestValue3, TestValue4 } let test : Test1 = .TestValue2 switch test { case .TestValue1: print("\(Test1.TestValue1)") case .TestValue2: print("\(Test1.TestValue2)") case .TestValue3: print("\(Test1.TestValue3)") case .TestValue4: print("\(Test1.TestValue4)") } //switch语句必须穷举所有的枚举值,否则不能通过编译,或者提供一个default分支,此时可以不穷举所有枚举值 //TestValue2 ~~~ 3、相关值 可以定义 Swift 的枚举存储任何类型的相关值,如果需要的话,每个成员的数据类型可以是各不相同的。枚举的这种特性跟其他语⾔中的可辨识联合(discriminated unions),标签联合(tagged unions),或者变体(variants)相似 ~~~ enum MyPhone { case Describe1(String, Int) case Describe2(String) } var phone1 = MyPhone.Describe1("小米", 1) switch phone1 { case MyPhone.Describe1(let param1, let param2) : print("\(param1), \(param2)") case MyPhone.Describe2(let param3): print(param3) } phone1 = .Describe2("小米1") switch phone1 { case MyPhone.Describe1(let param1, let param2) : print("\(param1), \(param2)") case MyPhone.Describe2(let param3): print(param3) } //小米, 1 //小米1 ~~~ 4、原始值 作为相关值的另⼀种选择,枚举成员可以被默认值(称为原始值)赋值,其中这些原始值具有相同的类型。 原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯⼀的。 注意: 原始值和相关值是不相同的。当你开始在你的代码中定义枚举的时候原始值是被预先填充的值。对于⼀个特定的枚举成员,它的原始值始终是相同的。 相关值是当你在创建⼀个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。 ~~~ enum OriginalValue : Int { case Age1 = 10 case Age2 = 20 case Age3 = 30 } print(OriginalValue.Age2.rawValue) //20 ~~~ (1)原始值的隐式赋值 ~~~ enum OriginalValue : Int { case Age1 = 10 case Age2 //第一个赋值为10,后面的将隐式赋值,隐式赋值的值依次递增1 case Age3 } print(OriginalValue.Age2.rawValue) //11 enum OriginalValue1 : Int { case Value1 //如果第一个没有被赋值,自动赋值为0 case Value2 = 3 case Value3 } print(OriginalValue1.Value1.rawValue) print(OriginalValue1.Value2.rawValue) print(OriginalValue1.Value3.rawValue) //0 //3 //4 ~~~ (2)使⽤原始值初始化枚举变量 如果在定义枚举类型的时候使⽤了原始值,那么将会⾃动获得⼀个初始化⽅法,这个⽅法将原始值类型作为参数,返回枚举成员或者 nil  。你可以使⽤这种初始化⽅法来创建⼀个新的枚举变量。 ~~~ enum ScoreLevel : Int { case Level1 = 1, Level2, Level3, Level4, Level5 } let scoreLevel = ScoreLevel(rawValue: 3) //返回值是可选类型 print(scoreLevel!) //Level3 ~~~ 5、递归枚举 算数表达式的⼀个重要特性是,表达式可以嵌套使⽤。例如,表达式 (5 + 4) * 2  乘号右边是⼀个数字,左边则是另⼀个表达式。因为数据是嵌套的,因⽽⽤来存储数据的枚举类型也许要⽀持这种嵌套————这表⽰枚举类型需要⽀持递归。 递归枚举(recursive enumeration)是⼀种枚举类型,表⽰它的枚举中,有⼀个或多个枚举成员拥有该枚举的其他成员作为相关值。使⽤递归枚举时,编译器会插⼊⼀个中间层。你可以在枚举成员前加上 indirect  来表⽰这成员可递归。 ~~~ enum ArithmeticExpression { case Number(Int) indirect case Addition(ArithmeticExpression, ArithmeticExpression) indirect case Multiplication(ArithmeticExpression, ArithmeticExpression) } //也可以在枚举类型开头加上 indirect 关键字来表⽰它的所有成员都是可递归的 indirect enum ArithmeticExpression1 { case Number(Int) //有⼀个或多个枚举成员拥有该枚举的其他成员作为相关值 case Addition(ArithmeticExpression1, ArithmeticExpression1) case Multiplication(ArithmeticExpression1, ArithmeticExpression1) } 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(5) let four = ArithmeticExpression.Number(4) let sum = ArithmeticExpression.Addition(five, four) //计算两个数相加 print(evaluate(sum)) //这里执行evalute函数,进去后匹配到.Addition分支,分支中left又是.Number类型,返回数值进行计算 let product = ArithmeticExpression.Multiplication(sum, ArithmeticExpression.Number(2)) print(evaluate(product)) //9 //18 ~~~
';