7.3 條件語句
我們總會遇到這樣的需求:
如果下雨就打雨傘,如果出太陽就打遮陽傘,其他情況不打傘
或者
成績在90分以上的學生獲得優(yōu)秀獎,在80分以上的獲得出色獎,在60以上的獲得努力獎,其他的被批評。
這就是條件,事情的發(fā)生很多都是有條件的。Swift 提供了兩種條件語句,if
和switch
。if
適合簡單的情況,比如:
男生請左轉(zhuǎn),女生請右轉(zhuǎn)
而 switch
適合相對復雜的情況,比如上面根據(jù)分數(shù)評等級的例子。
If
if
會執(zhí)行條件語句
,如果是true
則執(zhí)行一段代碼,否則跳過。如
var temperatureInCelsius = 16
if temperatureInCelsius <= 20 {
println("It's a little cold. Consider wearing a scarf.")
}
這個例子判斷了當前的天氣,如果低于5攝氏度,就輸出這句溫馨的關(guān)懷。
當然可以更復雜一些:
var temperaturInCelsius = 24
if temperaturInCelsius <= 20 {
println("It's a little cold. Consider wearing a scarf.")
} else {
println("It's not that cold. Wear a t-shirt.")
}
這段代碼多了一個else
分句,該分句就是我們平時說的,否則。這段代碼首先判斷了當前的溫度,如果低于20提示你要帶一條圍巾,否則穿一件t-shirt。
還可以更復雜一些:
var temperaturInCelsius = 32
if temperaturInCelsius <= 20 {
println("It's a little cold. Consider wearing a scarf.")
} else if temperaturInCelsius >= 30 {
println("It's really warm. Don't forget to wear sunscreen.")
} else {
println("It's not that cold. Wear a t-shirt.")
}
可見我們可以連續(xù)使用if
、else if
、else
,表達一個完整的意思。如果上面的一個if
或else if
的條件語句
為true
那么就會進入該if
或else if
的代碼區(qū)域執(zhí)行代碼,之后跳出整個if
,而不會繼續(xù)執(zhí)行后面的 else if
。
如果男生就向左轉(zhuǎn),否則向右轉(zhuǎn):
var gender = "Male"
if gender == "Male" {
println("Turn left")
} else {
println("Turn right")
}
如果下雨就打雨傘,如果出太陽就打遮陽傘,其他情況不打傘
var weather = "sunny"
if weather == "sunny" {
println("Take a bumbersoll with you")
} else if weather == "rainy" {
println("Take an umbrella with you")
}
成績在90分以上的學生獲得優(yōu)秀獎,在80分以上的獲得出色獎,在60以上的獲得努力獎,其他的被批評。
var score = 100
if score >= 90 {
println("Excellent")
// 代碼執(zhí)行完這句話,不會繼續(xù)執(zhí)行下面的判斷,而是跳出整個if
} else if score >= 80 {
println("Good")
} else if score >= 60 {
println("OK)
} else {
println("Work harder")
}
Switch
switch
用于較復雜的情況。switch
的標準格式如下:
switch VALUE_TO_TEST {
case VALUE_1:
ACTIONS_TO_VALUE_1
case VALUE_2,
VALUE_3:
ACTIONS_TO_VALUE_2_OR_VALUE_3
default:
ACTIONS_IF_NOT_MATCHED
}
每個switch
語句都是由多情況斷組成的,每個情況由關(guān)鍵字case
開始,case
后是進入這個情況的條件。除了由case
開始的情況外,還有由default
開始的,稱之為默認情況。每個情況都必須相應的代碼段,而不能為空。switch
根據(jù)VALUE_TO_TEST
的值,判斷該進入哪個情況執(zhí)行該情況,執(zhí)行相應的代碼。
每個switch
語句都需要是完備的。就是說每一個VALUE_TO_TEST
的可能值,都必須出現(xiàn)在一個情況中。如果由case
引導的情況沒有成功匹配VALUE_TO_TEST
的值,那么就會進入默認情況。如果由case
引導的情況不是完備的,則必須包含默認情況。
下面的例子判斷了一個字母是否為元音:
let someCharacter: Character = "e"
switch someCaracter {
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")
}
不同情況間不會穿越
與 C 和 Objective-C 不同,Swift 的switch
的情況不會穿越,除非顯式的指出我們需要穿越。
例如下面這段代碼,Swift 編譯器會報錯:
let anotherCharacter: Character = "a"
switch anotherCharacher {
case "a":
case "A":
println("The letter A")
default:
println("Not the letter A")
}
在 C 中,無論"a"
或者"A"
都會輸出"The letter A"
,并且還會繼續(xù)輸出"Not the letter A"
; 但是在 Swift 中,編譯器會報錯。這種情況我們應該使用 Swift 提供的多值匹配:
let anotherCharacter: Character = "a"
switch anotherCharacher {
case "a", "A":
println("The letter A")
default:
println("Not the letter A")
}
后面章節(jié)會介紹關(guān)鍵字
fallthrough
,該關(guān)鍵字可以使Swift的情況穿越
范圍匹配
當我們判斷一個數(shù)字的范圍時,多值匹配變得力不從心。例如我們想根據(jù)銀河中的星星個數(shù)輸出一句文字描述其數(shù)字的范圍:
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).")
元組匹配
Swift 的switch
支持同時匹配多個值,使用元組將其組合起來,成為一個元組變量,傳入switch
進行比較。比較兩個元組時,有時我們只想比較其中某個位置的值,此時我們可以用下劃線忽略不需要比較的位置。
這回我們用直角坐標系來舉個例子。我們在坐標系中繪制一個邊長為4的正方形,其四個定點分別在(2,2)、(2,-2)、(-2,-2)以及(-2,2)。然后我們判斷該坐標系中的一個點是處于原點、坐標軸上還是我們的方框內(nèi)。
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")
}
當somePoint
同時滿足多個情況時,第一個滿足的情況會被執(zhí)行,而其他的都會被跳過。
值綁定
switch
情況的條件語句可以進行值綁定,可以將值綁定到一個作用域為該情況代碼段的常量或變量上。
還是用直角坐標系舉例:
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))")
}
switch
語句判斷anotherPoint
是否在坐標軸上,如果是輸出其非0的坐標。
該例中第一個情況綁定了anotherPoint
的橫坐標,并將其縱坐標被限制為0,任何縱坐標為 0 的點都會進入這種情況,包含原點和其他 x 軸上的點。橫坐標被綁定在名為x
的常量上;第二個情況綁定了縱坐標,并限制橫坐標為0,除了原點外,所有 y 軸上的點都被匹配到這個情況中;而其他的所有不在坐標軸上的點都進入了第三個情況,我們分別綁定了該點的橫縱坐標。
因為所有以case
引導的情況已經(jīng)可以完備的表達點在直角坐標系的全部情況,所以不需要default
了。
Where
switch
的情況,除了可以進行值匹配以外還可以通過where
子句進行附加條件判斷。
我們還用直角坐標系舉例,我們想判斷一個點是否在直角坐標系的對角線上。
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")
}
三種情況都進行了值綁定,綁定后我們又進行了進一步條件判斷。第一個情況中,我們判斷該點的橫縱坐標是否相同,這樣的點在一三象限的角平分線上;第二個情況中,我們判斷改點的橫縱坐標是否相反,這樣的點在二四象限的角平分線上;其余的情況通過不帶where
子句的值綁定匹配。