枚举类型
枚举语法
enum CompassPoint {
case North
case South
case East
case West
}
注意:与C或者Objective-C不同的是,在Swift语言中枚举类型的成员初始的时候不会被默认赋值成整数值,在CompassPoint这个例子中,North, South, East, West默认不会隐式的等于0,1,2,3。取而代之的是不同的枚举成员将要用什么类型以及赋值什么值都是可以自己控制的,可以在定义CompassPoint这个枚举的时候指定.
多个成员还可以用一行来定义,他们之间用逗号分割
enum Plant{
case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
每个枚举的定义都是定义了一个全新的类型,就像Swfit中的其他的类型一样,枚举的名称(CompassPoint, Plant)应该是以一个大写字母开头,让他们是单数类型而不是复数类型,从而让他们可以不言而喻。
var directionToHead = CompassPoint.West
当directionToHead在初始化过程中被赋值成CompassPoint中的某一个可能的值的时候,它的类型就可以被推测出来来了。一旦directionToHead被声明成是CompassPoint类型,那么你就可以简短的使用逗号表达式来给它赋值成其他的CompassPoint当中的值了:
directionToHead = .East
Switch 语句来匹配枚举
directionToHead = .South
switch directionToHead {
case .North:
println("Lots of planets have a north")
case .South:
println("Watch out for penguins")
case .East:
println("Where the sun rises")
case .West:
println("Where the skies are blue")
}
// prints "Watch out for penguins"
let somePlanet = Plant.Earth
switch somePlanet {
case .Earth:
println("Mostly harmless")
default:
println("Not a safe place for humans")
}
// 输出 "Mostly harmless"
关联值
在Swift中当你定义一个枚举成员的时候,你可以给他关联任何的类型,而且如果需要的话每个成员可以有不同的关联类型。枚举类型的这个特性和其他语言当中的辨别联合,标记联合或者变体很像。
一个可以定义两个格式的产品条形码的枚举看起来是这样的:
enum Barcode {
case UPCA(Int, Int, Int, Int)
case QRCode(String)
}
可以这么理解
定义了一个叫做Barcode的枚举类型,它可以有一个UPCA成员,这个成员关联了一个包含4个整型数值的元组,同时这个枚举类型还有一个QRCode成员,关联了一个字符串
这个定义不会生成任何的整型或者字符串值,他只是定义了当一个不可变变量或者变量等于Barcode.UPCA或者Barcode.QRCode的时候它被关联的值的类型
var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)
productBarcode = .QRCode("ABCDEFGHIJKLMNOPQRST")
这两个不同的类型可以用Switch语句来做检查。同时,在switch语句中他们相关联的值也可以被获取到。你可以把关联的值当做不可变变量(用let来开头),或者可变变量(用var开头)以在switch的控制体当中使用。
switch productBarcode {
case .UPCA(let numberSystem, let manufacturer, let product, let check):
println("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
case .QRCode(let productCode):
println("QR code: \(productCode).")
}
// prints "QR code: ABCDEFGHIJKLMNOP."
如果一个枚举成员关联的所有值都被当做不可变变量或者可变变量来使用,那么你可以在成员名称之前只放一个let或者var来达到目的
switch productBarcode {
case let .UPCA(numberSystem, manufacturer, product, check):
println("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
case let .QRCode(productCode):
println("QR code: \(productCode).")
}
// prints "QR code: ABCDEFGHIJKLMNOP."
原始值(Raw Values)
不同于关联值,枚举类型的成员还可以预设置默认值(我们叫他原始值),这些值的类型是相同的。
enum ASCIIControlCharacter: Character {
case Tab = "\t"
case LineFeed = "\n"
case CarriageReturn = "\r"
}
注意:原始值与关联值不同。原始值应该是在你定义枚举的代码中被设置为预填充值的,就像上述三个ASCII码。对于一个特定的枚举成员的原始值始终是相同的。关联值是当你创建一个基于枚举的成员的新的常量或变量的时候设置的,并且每次都可以是不同的。
原始值可以是字符串,字符或者其他任何的整型或者浮点型等数字类型。每个原始值在他属的枚举类型定义的时候都应该是不同的。如果原始值是整数类型,那么当其他枚举成员没有设置原始值的时候,他们的原始值是这个整型原始值自增长设置的。
enum Planet: Int {
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
获取原始值
let earthOrder = Planet.Earth.rawValue
earthsOrder is 3
从rawValue初始化
let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet is of type Planet? and equals Planet.Uranus
不是所有可能int值都能找到一个匹配的Planet,所以,原始值初始化常常返回一个可选的枚举成员,上面的possiblePlanet的类型是Planet?
如果你试图去找到一个在位置9的Planet,这个可选的Planet值通过原始值去初始化将返回nil
let positionToFind = 9
if let somePlanet = Planet(rawValue: positionToFind) {
switch somePlanet {
case .Earth:
println("Mostly harmless")
default:
println("Not a safe place for humans")
}
} else {
println("There isn't a planet at position \(positionToFind)")
}
// prints "There isn't a planet at position 9"