switch

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塊中的代碼執行完畢后,程序會終止switch語句,而不會繼續執行下一個case塊。這也就是說,不需要在case塊中顯式地使用break語句。這使得switch語句更安全、更易用,也避免了因忘記寫break語句而產生的錯誤。

每一個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風格的落入(fallthrough)的特性,你可以在每個需要該特性的case分支中使用fallthrough關鍵字。下面的例子使用fallthrough來創建一個數字的描述語句。

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關鍵字不會檢查它下一個將會落入執行的case中的匹配條件。fallthrough簡單地使代碼執行繼續連接到下一個case中的執行代碼,這和C語言標準中的switch語句特性是一樣的。

范圍匹配

case塊的模式也可以是一個值的范圍。下面的例子展示了如何使用范圍匹配來輸出任意數字對應的自然語言格式:

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。但是,如果存在多個匹配,那么只會執行第一個被匹配到的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。

一旦聲明了這些臨時的常量,它們就可以在其對應的case塊里引用。

請注意,這個switch語句不包含默認塊。這是因為最后一個case——case let(x, y)聲明了一個可以匹配余下所有值的元組。這使得switch語句已經完備了,因此不需要再書寫默認塊。

在上面的例子中,x和y是常量,這是因為沒有必要在其對應的case塊中修改它們的值。然而,它們也可以是變量——程序將會創建臨時變量,并用相應的值初始化它。修改這些變量只會影響其對應的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
產生一個帶標簽的語句是通過在該語句的關鍵詞的同一行前面放置一個標簽,并且該標簽后面還需帶著一個冒號。下面是一個while循環體的語法,同樣的規則適用于所有的循環體和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語句跳轉控制去執行while循環體后的第一行代碼,while結束,游戲結束。

continue gameLoop語句結束本次while循環的迭代,開始下一次循環迭代。

NOTE:如果上述的break語句沒有使用gameLoop標簽,那么它將會中斷switch代碼塊而不是while循環體。使用gameLoop標簽清晰的表明了break想要中斷的是哪個代碼塊。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容