枚举Enumerations ********************/
/*
枚举语法
使用Switch语句匹配枚举值
关联值
原始值
递归枚举
*/
// 枚举为一组相关的值定义了一个共同的类型,使你可以在你的代码中以类型安全的方式来使用这些值
// Swift中的枚举值更加灵活,不必给每一个枚举成员提供值.如果提供了(原始值),则该值的类型是字符串,字符或是一个整形值或浮点值
// 枚举成员可以指定任意类型的关联值存储到枚举成员中,就像其他语言中的联合体unions和变体variants.每一个枚举成员都可以有适当类型的关联值
// Swift中,枚举类型是一等(first-class)类型,他们采用了很多再传统上只做类所支持的特性.
// 计算机属性:用于提供枚举值的附加信息
// 实例方法:用于提供和枚举值相关联的功能
// 枚举也可以定义构造函数提供一个初始值,可以在原始实现的基础上扩展他们的功能,还可以遵循协议类提供标准的功能
// 枚举语法
使用enum关键字创建
enum
// 枚举定义放在这
}
// 指南针方向
enum
case
case
case
case
}
.East
// case 关键字来定义一个新的枚举成员值
// 这些枚举值不会再直接赋予一个整形的0,1,2,3,这种值了,他们本身就是完备的值,这些值的类型是已经明确定义好的CompassPoint类型
// 多个成员值可以出现在同一行,用逗号隔开
enum
case
}
var directionToHead = CompassPoint.North
一旦directionToHead被声明为Planet类型,那么可以更简略
= .East
// 在使用具有显式类型的枚举值时,这种写法让代码具有更好的可读性
使用Switch语句匹配枚举值:
= .South
switch directionToHead{
case
print("Lots of planets have a north")
case
print("Watch out for penguins")
case
print("Where the sun rises")
case
print("Where the skies are blue")
}
输出"Watch out for penguins"
// Switch语句必须穷举所有情况
let somePlanet = Planet.Earth
switch somePlanet{
case
print("Mostly harmless")
:
print("Not a safe place for humans")
}
输出Mostly harmless
关联值
enum
case
case
}
理解为:
定义一个名为Barcode的枚举类型,它的一个成员值是具有(Int,Int,Int,Int)类型关联值的UPCA,另一个成员值是具有String类型关联值的QRCode
这个定义不提供任何Int和 String类型的关联值,他只是定义了,当Barcode常量和变量等于Barcode.UPCA或Barcode.QRCode时,可以存储的关联值的类型
var productBarcode = Barcode.UPCA(8,85909, 51226,3)
创建一个productBarcode的变量,并将Barcode.UPCA赋值给它,关联的元组为(8, 85909, 51226, 3)
// 还可以给个不同类型的值
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
// Barcode类型的常量和变量可以存储一个.UPCA或者一个.QRCode(连同它们的关联值),但是在同一时间只能存储这两个值中的一个
switch productBarcode{
case .UPCA(let numberSystem,let manufacturer,let product,let
print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
case .QRCode(let
print("QR code:\(productCode).")
}
输出
// 如果一个枚举成员的所有关联值都被提取为变量,或者都被提取为变量,为了简洁,可以在成员名称前标注一个let或者var:
switch productBarcode{
case let
print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
case let
print("QR code:\(productCode).")
}
原始值
// 枚举成员可以被默认值(称为原始值)预填充,这些原始值的类型必须相同.
enum ASCIIControlCharcter:Character{
case Tab = "\t"
case UneFeed = "\n"
case CarriageReturn = "\r"
}
// 原始值可以是字符串,字符,或者任意整型值或浮点型值.
// 原始值是在定义枚举时被预先填充的值,每个原始值在枚举声明中必须是唯一的.
// 关联值是创建一个基于枚举成员的常量或变量时才设置的值,枚举成员的关联值可以变化.
原始值的隐式赋值
// 在使用原始值为整数或者字符串类型的枚举时,不需要显式的为每一个枚举成员设置原始值,Swift将会自动赋值
// 如果使用整数为原始值时,隐式赋值的值依次递增1,如果第一个枚举值没有设置原始值,那么原始值默认为0
// 下面的枚举值是对之前Planet这个枚举值的一个细化,利用整型的原始值来表示每个行星在太阳系中的顺序
enum Planet1:Int
case Mercury = 1,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune
}
// 当使用字符串作为枚举类型的原始值时,每个枚举成员的隐式原始值为该枚举成员的名称
// 下面的例子是CompassPoint枚举的细化,使用字符串类型的原始值来表达各个方向的名称
enum CompassPoint1:String{
case
}
的隐式原始值South,依次类推
// 使用枚举成员的rawValue属性可以访问该枚举成员的原始值:
let earthsOrder = Planet1.Earth.rawValue
print(earthsOrder)
let sunsetDirection = CompassPoint1.West.rawValue
/* 如果这个枚举不写类型,是不是就意味着没有默认值,点不出来rawValue */
使用原始值初始化枚举实例
// 如果在定义枚举类型的时候使用了原始值,那么将会自动获得一个初始化方法
// 如果这个方法接收一个叫做rawValue的参数,参数类型为原始值类型,返回值为枚举成员或nil.
// 你可以使用这个初始化方法来创建一个新的枚举实例
// 这个例子利用原始值7创建了枚举成员Uranus:
let possiblePlanet1 = Planet1(rawValue: 7)
类型为Planet? 值为Planet.Uranus
// 注意:原始值构造器是一个可失败构造器,因为并不是每一个原始值都有与之对应的枚举成员
// 如:如果你试图寻找一个位置为9的行星,通过原始值构造器返回的可选Planet值将是nil
let positionToFind = 9
if let somePlanet1 =Planet1(rawValue: positionToFind)
{
switch
case
print("Mostly harmless")
default:
print("Not a safe place for humans")
}
else
print("There isn't a planet at position\(positionToFind)")
}
这个例子使用了可选绑定(optional binding),
递归枚举
// 当各种可能的可以被穷举时,非常适合使用枚举进行数据建模.
// 例如可以用枚举来表示用于简单整数运算的操作符,这些操作符让你可以讲简单的算术表达式,例如整数5,结合为更为复杂的表达式,例如5+4
// 算术表达式的一个重要特性:表达式可以嵌套使用.例如(5+4)*2
// 乘号右边是一个数字,左边则是另一个表达式.
// 因为数据是嵌套的,因而用来存储数据的枚举类型也需要支持这种嵌套----这意味着枚举类型需要支持递归
// 递归枚举(Recursive enumerations)是一种枚举类型,它有一个或多个枚举成员使用该枚举类型的实例作为关联值.使用递归枚举时,编译器会插入一个间接层,你可以在枚举成员前加上indirect来表示该成员可递归.
enum
case
indirect case
indirect case
}
// 也可以在枚举开头加上indirect(间接的,迂回的,非直接了当的)关键字来表明它的所有成员都是可递归的
indirect enum
case
case
case
}
// 上面定义的枚举类型可以存储
//ArithmeticExpression.Multiplication(ArithmeticExpression.Multiplication(<#T##ArithmeticExpression#>, <#T##ArithmeticExpression#>), <#T##ArithmeticExpression#>)
// 上面定义的枚举类型可以存储三种算术表达式:纯数字,两个表达式相加,两个表达式相乘.枚举成员Addition和Multiplication的关联值也是算术表达式---这些关联值使得嵌套表达式成为可能
// 要操作具有递归性质的数据结构,使用递归函数是一种直接了当的方式,
// 例如:下面是一个对算术表达式求值的函数
func evaluate(expression:ArithmeticExpression)->Int{
switch
case .Number(let
return
case .Addition(let left,let
return evaluate(left) +evaluate(right)
case .Multiplication(let left,let
return evaluate(left) *evaluate(right)
}
}
计算(5 + 4) * 2
let five = ArithmeticExpression.Number(5)
let four = ArithmeticExpression.Number(4)
let two = ArithmeticExpression.Number(2)
print(evaluate(two))
let sum = ArithmeticExpression.Addition(five,four)
let product = ArithmeticExpression.Multiplication(sum,two)
print(evaluate(product))
// 该函数如果遇到纯数字,就直接返回该数字的值,如果遇到的是加法或者是乘法,就分别计算左右的值,然后进行计算