switch
switch語句最簡單的形式就是把某個值與一個或若干個相同類型的值作比較:
switch 'some value to consider' {
case 'value 1':
'respond to value 1'
case 'value 2',
'value 3':
'respond to value 2 or 3'
default:
'otherwise, do something else'
}
下面的例子使用switch語句來匹配一個名為someCharacter的小寫字符:
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
println("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
println("\(someCharacter) is a consonant")
default: println("\(someCharacter) is not a vowel or a consonant")
}
// prints "e is a vowel"
在 Swift 中流纹,當匹配的case塊中的代碼執(zhí)行完畢后,程序會終止switch語句,而不會繼續(xù)執(zhí)行下一個case塊。這也就是說,不需要在case塊中顯式地使用break語句。這使得switch語句更安全、更易用摊唇,也避免了因忘記寫break語句而產(chǎn)生的錯誤。
每一個case塊都必須包含至少一條語句涯鲁。像下面這樣書寫代碼是無效的巷查,因為第一個case塊是空的:
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a":
case "A":
println("The letter A")
default:
println("Not the letter A")
}
// this will report a compile-time error
不像C語言里的switch語句有序,在 Swift 中,switch語句不會同時匹配"a"和"A"岛请。相反的旭寿,上面的代碼會引起編譯期錯誤:case "a": does not contain any executable statements——這就避免了意外地從一個case塊貫穿到另外一個,使得代碼更安全崇败、也更直觀盅称。
一個case也可以包含多個模式,用逗號把它們分開(如果太長了也可以分行寫):
switch `some value to consider` {
case `value 1`,
`value 2`:
`statements`
}
注意:如果想要貫穿特定的case塊中后室,請使用fallthrough語句
Fallthrough
如果你確實需要C風(fēng)格的落入(fallthrough)的特性缩膝,你可以在每個需要該特性的case分支中使用fallthrough關(guān)鍵字。下面的例子使用fallthrough來創(chuàng)建一個數(shù)字的描述語句岸霹。
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer."
}
println(description)
// prints "The number 5 is a prime number, and also an integer."
NOTE:fallthrough關(guān)鍵字不會檢查它下一個將會落入執(zhí)行的case中的匹配條件疾层。fallthrough簡單地使代碼執(zhí)行繼續(xù)連接到下一個case中的執(zhí)行代碼,這和C語言標準中的switch語句特性是一樣的贡避。
范圍匹配
case塊的模式也可以是一個值的范圍云芦。下面的例子展示了如何使用范圍匹配來輸出任意數(shù)字對應(yīng)的自然語言格式:
let count = 3_000_000_000_000
let countedThings = "stars in the Milky Way"
var naturalCount: String
switch count {
case 0:
naturalCount = "no"
case 1...3:
naturalCount = "a few"
case 4...9:
naturalCount = "several"
case 10...99:
naturalCount = "tens of"
case 100...999: naturalCount = "hundreds of"
case 1000...999_999: naturalCount = "thousands of"
default:
naturalCount = "millions and millions of"
}
println("There are \(naturalCount) \(countedThings).")
// prints "There are millions and millions of stars in the Milky Way."
元組 (Tuple)
你可以使用元組在同一個switch語句中測試多個值。元組中的元素可以是值贸桶,也可以是范圍。另外桌肴,使用下劃線(_)來匹配所有可能的值皇筛。
下面的例子展示了如何使用一個(Int, Int)類型的元組來分類下圖中的點(x, y):
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
println("(0, 0) is at the origin")
case (_, 0):
println("(\(somePoint.0), 0) is on the x-axis")
case (0, _):println("(0, \(somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
println("(\(somePoint.0), \(somePoint.1)) is inside the box")
default:println("(\(somePoint.0), \(somePoint.1)) is outside of the box")
}
// prints "(1, 1) is inside the box"
不像C語言,Swift 允許多個case匹配同一個值坠七。實際上水醋,在這個例子中,點(0, 0)可以匹配所有四個case彪置。但是拄踪,如果存在多個匹配,那么只會執(zhí)行第一個被匹配到的case塊拳魁』掏考慮點(0, 0)會首先匹配case (0, 0),因此剩下的能夠匹配(0, 0)的case塊都會被忽視掉潘懊。
值綁定 (Value Bindings)
case塊的模式允許將匹配的值綁定到一個臨時的常量或變量姚糊,這些常量或變量在該case塊里就可以被引用了——這種行為被稱為值綁定。
下面的例子展示了如何在一個(Int, Int)類型的元組中使用值綁定來分類下圖中的點(x, y):
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
println("on the x-axis with an x value of \(x)")
case (0, let y):
println("on the y-axis with a y value of \(y)")
case let (x, y):
println("somewhere else at (\(x), \(y))")
}
// prints "on the x-axis with an x value of 2"
這三個case都聲明了常量x和y的占位符授舟,用于臨時獲取元組anotherPoint的一個或兩個值救恨。第一個case——case (let x, 0)將匹配一個縱坐標為0的點,并把這個點的橫坐標賦給臨時的常量x释树。類似的肠槽,第二個case——case (0, let y)將匹配一個橫坐標為0的點擎淤,并把這個點的縱坐標賦給臨時的常量y。
一旦聲明了這些臨時的常量秸仙,它們就可以在其對應(yīng)的case塊里引用嘴拢。
請注意,這個switch語句不包含默認塊筋栋。這是因為最后一個case——case let(x, y)聲明了一個可以匹配余下所有值的元組炊汤。這使得switch語句已經(jīng)完備了,因此不需要再書寫默認塊弊攘。
在上面的例子中抢腐,x和y是常量,這是因為沒有必要在其對應(yīng)的case塊中修改它們的值襟交。然而迈倍,它們也可以是變量——程序?qū)?chuàng)建臨時變量,并用相應(yīng)的值初始化它捣域。修改這些變量只會影響其對應(yīng)的case塊啼染。
Where
case塊的模式可以使用where語句來判斷額外的條件。
下面的例子把下圖中的點(x, y)進行了分類:
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
println("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
println("(\(x), \(y)) is on the line x == -y")
case let (x, y):
println("(\(x), \(y)) is just some arbitrary point")
}
// prints "(1, -1) is on the line x == -y"
Labeled Statements
產(chǎn)生一個帶標簽的語句是通過在該語句的關(guān)鍵詞的同一行前面放置一個標簽焕梅,并且該標簽后面還需帶著一個冒號迹鹅。下面是一個while循環(huán)體的語法,同樣的規(guī)則適用于所有的循環(huán)體和switch代碼塊贞言。
label name: while condition {
statements
}
如:
gameLoop: while square != finalSquare {
if ++diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// diceRoll will move us to the final square, so the game is over
break gameLoop
case let newSquare where newSquare > finalSquare: // diceRoll will move us beyond the final square, so roll again
continue gameLoop
default:// this is a valid move, so find out its effect square += diceRoll square += board[square] }
}
println("Game over!")
break gameLoop語句跳轉(zhuǎn)控制去執(zhí)行while循環(huán)體后的第一行代碼斜棚,while結(jié)束,游戲結(jié)束该窗。
continue gameLoop語句結(jié)束本次while循環(huán)的迭代弟蚀,開始下一次循環(huán)迭代。
NOTE:如果上述的break語句沒有使用gameLoop標簽酗失,那么它將會中斷switch代碼塊而不是while循環(huán)體义钉。使用gameLoop標簽清晰的表明了break想要中斷的是哪個代碼塊。