·枚举语法
·匹配枚举值与Switch语句
·相关值
·原始值
枚举定义了一个通用类型的一组相关的值,是你可以在你的代码中以一个安全的方式来使用这些值。
Swift只能中不必给每一个枚举成员提供一个值。
提供给每个枚举成员的可以是一个字符串,一个字符,或是一个整型值或浮点值。
此外,枚举成员可以指定任何类型的相关值存储到枚举成员值中,就像其他语言中的联合体(unions)和变体(variants)。你可以定义一组通用的相关成员作为枚举的一部分,每一组都有不同的一组与它相关的适当类型的值。
在Swift中,枚举类型是一等类型(first-class)。他们采用了很多传统上只被类(class)所支持的特征,例如计算型属性(computed properties),用于提供关于枚举当前值的附加信息;实例方法(instance methods),用于提供和枚举所代表的值相关联的功能;枚举也可以定义构造函数(initializers)来提供一个初始成员值;可以在原始的实现基础上扩展它们的功能;可以遵守协议(protocols)来提供标准的功能。
·枚举语法
使用enum关键字并且把它们的整个定义放在一对大括号内。
enum SomeEnumeration{
// enumeration definition goes here
}
enum CompassPoint{
case North
case South
case East
case West
}
一个枚举中被定义的值(例如North)是枚举的成员值(成员)。case关键词表名新一行成员值将被定义。
注意:与C/OC不一样的是,Swift的枚举成员在被创建时不会被赋予一个默认的整数值。
多个成员值可以出现在同一行上,用逗号隔开:
enum Planet{
case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Nepturn
}
每个枚举定义了一个全新的类型。像Swift中其他类型一样,必须以一个大写字母开头。给枚举类型起一个单数名字而不是复数名字。
enum CompassPoint{
case North
case South
case East
case West
}
var directiOnToHead= CompassPoint.West
directionToHead的类型被推断当它被CompassPoint的一个可能值初始化。一旦directionToHead被声明为一个CompassPoint,你可以使用更短的点(.)语法将其设置为另一个CompassPoint的值:
var directiOnToHead= CompassPoint.West
directiOnToHead= .North
directionToHead的类型已知时,当设定它的值时,你可以不在写类型名。使用显示类型的枚举值可以让代码具有更好的可读性。
·匹配枚举值和Switch语句
你可以匹配单个枚举值和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")
}
// 输出 "Watch out for penguins”
当考虑一个枚举的成员们时,一个switch语句必须全面。如果忽略了.west这种情况,代码就将无法通过编译。
当不需要匹配每个枚举成员的时候,你可以提供一个默认default分支来涵盖所有未明确被提出的任何成员:
enum Planet{
case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Nepturn
}
let somePlanet = Planet.Earth
switch somePlanet{
case .Earth:
println("Mostly harmless")
default:
println("Not a safe place for humans")
}
//Mostly harmless
·相关值(Associated Values)
为Planet.Earth设置一个常量或者变量,并且在以后查看这个值。如果能够把其他类型的相关值和成员值一起储存起来会很有用。这能让你存储成员值之外的自定义信息,并且当你每次在代码中使用改成员时允许这个信息产生变化。
你可以定义Swift的枚举储存任何类型的相关值,如果你需要的话,每个成员的数据类型可以是各不相同的。枚举的这个特性跟其他语言中的可辨识联合(discriminated unions),标签联合(tagged unions),或者变体(variants)相似。
enum Barcode{
case UPCA(Int, Int, Int)
case QRCode(String)
}
var productBarcode = Barcode.UPCA(8, 85909_51226,3)
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
可以在switch的case分支代码中提取每个相关值作为一个常量(用let前缀)或者作为一个变量(用var前缀)来使用:
enum Barcode{
case UPCA(Int, Int, Int)
case QRCode(String)
}
var productBarcode = Barcode.UPCA(8, 85909_51226,3)
switch productBarcode{
case .UPCA(let numberSystem, let identifier, let check):
println("UPC-A with value of \(numberSystem),\(identifier),\(check).")
case .QRCode(let productCode):
println("QR code with value of \(productCode).")
}
//UPC-A with value of 8,8590951226,3.
如果一个枚举成员的所有相关值被提取为常量,或者他们全部被提取为变量,为了简洁,你可以只放置一个var或者let标注在成员名称前:
enum Barcode{
case UPCA(Int, Int, Int)
case QRCode(String)
}
var productBarcode = Barcode.QRCode("ABCDEFGHIJKLMNOP")
switch productBarcode{
case let .UPCA(numberSystem,identifier,check):
println("UPC-A with value of \(numberSystem),\(identifier),\(check).")
case let .QRCode(productCode):
println("QR code with value of \(productCode).")
}
//QR code with value of ABCDEFGHIJKLMNOP.
·原始值(Raw Values)
作为相关值的代替,枚举成员可以被默认值(称为原始值)预先填充,其中这些原始值具有相同的类型。
例子:一个枚举成员存储原始ASCII值。
enum ASCIIControlCharacter: Character{
case Tab = "\t"
case LineFeed = "\n"
case CarriageReturn = "\r"
}
在这里,称为ASCIIControlCharacter的枚举的原始值类型被定义为字符型Character,并被设置了一些比较常见的ASCII控制字符。
注意:原始值和相关值是不相同的。
对于一个特定的枚举成员,它的原始值始终是相同的。相关值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做的时候,他的值可以是不同的。
原始值可以是字符串,字符或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。当整型值被用于原始值,如果其他枚举成员没有值时,他们会自动递增。
enum Planet: Int{
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Nepturn
}
使用枚举成员的toRaw方法可以访问该枚举成员的原始值:
enum Planet: Int{
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Nepturn
}
let earthsOrder = Planet.Earth.toRaw()
println(earthsOrder)
//3
使用枚举的fromRaw方法来试图找到具有特定原始值的枚举成员:
let possiblePlanet = Planet.fromRaw(7)
然而,并非所有可能的Int值都可以找到一个匹配的行星。fromRaw方法可以放回一个可选的枚举成员。
enum Planet: Int{
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Nepturn
}
let positiOnToFind= 9
if let somePlanet = Planet.fromRaw(positionToFind){
switch somePlanet{
case .Earth:
println("Mostly Harmless")
default:
println("Not a safe for humans")
}
}else{
println("There is not a planet at position \(positionToFind)")
}
//There is not a planet at position 9