模式代表單個值或者復(fù)合值的結(jié)構(gòu)。例如,元組 (1, 2)
的結(jié)構(gòu)是由逗號分隔的,包含兩個元素的列表。因?yàn)槟J酱硪环N值的結(jié)構(gòu),而不是特定的某個值,你可以利用模式來匹配各種各樣的值。比如,(x, y)
可以匹配元組 (1, 2)
,以及任何含兩個元素的元組。除了利用模式匹配一個值以外,你可以從復(fù)合值中提取出部分或全部值,然后分別把各個部分的值和一個常量或變量綁定起來。
Swift 中的模式分為兩類:一種能成功匹配任何類型的值,另一種在運(yùn)行時(shí)匹配某個特定值時(shí)可能會失敗。
第一類模式用于解構(gòu)簡單變量、常量和可選綁定中的值。此類模式包括通配符模式、標(biāo)識符模式,以及包含前兩種模式的值綁定模式和元組模式。你可以為這類模式指定一個類型注解,從而限制它們只能匹配某種特定類型的值。
第二類模式用于全模式匹配,這種情況下你試圖匹配的值在運(yùn)行時(shí)可能不存在。此類模式包括枚舉用例模式、可選模式、表達(dá)式模式和類型轉(zhuǎn)換模式。你在 switch
語句的 case
標(biāo)簽中,do
語句的 catch
子句中,或者在 if
、while
、guard
和 for-in
語句的 case
條件句中使用這類模式。
模式語法
模式 → 標(biāo)識符模式 類型注解可選
模式 → 值綁定模式
模式 → 枚舉用例模式
模式 → 可選模式
模式 → 類型轉(zhuǎn)換模式
模式 → 表達(dá)式模式
通配符模式由一個下劃線(_
)構(gòu)成,用于匹配并忽略任何值。當(dāng)你想忽略被匹配的值時(shí)可以使用該模式。例如,下面這段代碼在閉區(qū)間 1...3
中迭代,每次迭代都忽略該區(qū)間的當(dāng)前值:
for _ in 1...3 {
// ...
}
通配符模式語法
wildcard-pattern
通配符模式 → _
標(biāo)識符模式匹配任何值,并將匹配的值和一個變量或常量綁定起來。例如,在下面的常量聲明中,someValue
是一個標(biāo)識符模式,匹配了 Int
類型的 42
:
let someValue = 42
當(dāng)匹配成功時(shí),42
被綁定(賦值)給常量 someValue
。
如果一個變量或常量聲明的左邊是一個標(biāo)識符模式,那么這個標(biāo)識符模式是值綁定模式的子模式。
標(biāo)識符模式語法
identifier-pattern
標(biāo)識符模式 → 標(biāo)識符
值綁定模式把匹配到的值綁定給一個變量或常量。把匹配到的值綁定給常量時(shí),用關(guān)鍵字 let
,綁定給變量時(shí),用關(guān)鍵字 var
。
在值綁定模式中的標(biāo)識符模式會把新命名的變量或常量與匹配到的值做綁定。例如,你可以拆開一個元組,然后把每個元素綁定到相應(yīng)的標(biāo)識符模式中。
let point = (3, 2)
switch point {
// 將 point 中的元素綁定到 x 和 y
case let (x, y):
print("The point is at (\(x), \(y)).")
}
// 打印“The point is at (3, 2).”
在上面這個例子中,let
會分配到元組模式 (x, y)
中的各個標(biāo)識符模式。因此,switch
語句中 case let (x, y):
和 case (let x, let y):
的匹配效果是一樣的。
值綁定模式語法
value-binding-pattern
元組模式是由逗號分隔的,具有零個或多個模式的列表,并由一對圓括號括起來。元組模式匹配相應(yīng)元組類型的值。
你可以使用類型注解去限制一個元組模式能匹配哪種元組類型。例如,在常量聲明 let (x, y): (Int, Int) = (1, 2)
中的元組模式 (x, y): (Int, Int)
只匹配兩個元素都是 Int
類型的元組。
當(dāng)元組模式被用于 for-in
語句或者變量和常量聲明時(shí),它僅可以包含通配符模式、標(biāo)識符模式、可選模式或者其他包含這些模式的元組模式。比如下面這段代碼就不正確,因?yàn)?(x, 0)
中的元素 0
是一個表達(dá)式模式:
let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]
// 下面的代碼是錯誤的
for (x, 0) in points {
/* ... */
}
只包含一個元素的元組模式的圓括號沒有效果,模式只匹配這個單個元素的類型。舉例來說,下面的語句是等效的:
let a = 2 // a: Int = 2
let (a) = 2 // a: Int = 2
let (a): Int = 2 // a: Int = 2
元組模式語法
tuple-pattern
元組模式 → ( 元組模式元素列表可選 )
元組模式元素列表 → 元組模式元素 | 元組模式元素 , 元組模式元素列表
tuple-pattern-element
元組模式元素 → 模式
枚舉用例模式匹配現(xiàn)有的某個枚舉類型的某個用例。枚舉用例模式出現(xiàn)在 switch
語句中的 case
標(biāo)簽中,以及 if
、while
、guard
和 for-in
語句的 case
條件中。
如果你準(zhǔn)備匹配的枚舉用例有任何關(guān)聯(lián)的值,則相應(yīng)的枚舉用例模式必須指定一個包含每個關(guān)聯(lián)值元素的元組模式。關(guān)于使用 switch
語句來匹配包含關(guān)聯(lián)值的枚舉用例的例子,請參閱 關(guān)聯(lián)值。
枚舉用例模式同樣會匹配那些被包裝成可選值的用例。簡化的語法能將可選模式過濾掉。注意,由于 Optional
是枚舉實(shí)現(xiàn)的,.none
和 .some
都會作為枚舉類型的用例出現(xiàn)在 switch 中。
enum SomeEnum { case left, right }
let x: SomeEnum? = .left
switch x {
case .left:
print("Turn left")
case .right:
print("Turn right")
case nil:
print("Keep going straight")
}
// 打印 "Turn left"
枚舉用例模式語法
enum-case-pattern
枚舉用例模式 → 類型標(biāo)識可選 . 枚舉用例名 元組模式可選
可選模式匹配包裝在一個 Optional(Wrapped)
或者 ExplicitlyUnwrappedOptional(Wrapped)
枚舉中的 Some(Wrapped)
用例中的值??蛇x模式由一個標(biāo)識符模式和緊隨其后的一個問號組成,可以像枚舉用例模式一樣使用。
由于可選模式是 Optional
和 ImplicitlyUnwrappedOptional
枚舉用例模式的語法糖,下面兩種寫法是等效的:
let someOptional: Int? = 42
// 使用枚舉用例模式匹配
if case .Some(let x) = someOptional {
print(x)
}
// 使用可選模式匹配
if case let x? = someOptional {
print(x)
}
可選模式為 for-in
語句提供了一種迭代數(shù)組的簡便方式,只為數(shù)組中非 nil
的元素執(zhí)行循環(huán)體。
let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
// 只匹配非 nil 的元素
for case let number? in arrayOfOptinalInts {
print("Found a \(number)")
}
// Found a 2
// Found a 3
// Found a 5
可選模式語法
optional-pattern
可選模式 → 標(biāo)識符模式 ?
有兩種類型轉(zhuǎn)換模式,is
模式和 as
模式。is
模式只出現(xiàn)在 switch
語句中的 case
標(biāo)簽中。is
模式和 as
模式形式如下:
is
類型
模式
as類型
is
模式僅當(dāng)一個值的類型在運(yùn)行時(shí)和 is
模式右邊的指定類型一致,或者是其子類的情況下,才會匹配這個值。is
模式和 is
運(yùn)算符有相似表現(xiàn),它們都進(jìn)行類型轉(zhuǎn)換,但是 is
模式?jīng)]有返回類型。
as
模式僅當(dāng)一個值的類型在運(yùn)行時(shí)和 as
模式右邊的指定類型一致,或者是其子類的情況下,才會匹配這個值。如果匹配成功,被匹配的值的類型被轉(zhuǎn)換成 as
模式右邊指定的類型。
關(guān)于使用 switch
語句配合 is
模式和 as
模式來匹配值的例子,請參閱 Any 和 AnyObject 的類型轉(zhuǎn)換。
類型轉(zhuǎn)換模式語法
type-casting-pattern
is-pattern
is 模式 → is 類型
as-pattern
表達(dá)式模式代表表達(dá)式的值。表達(dá)式模式只出現(xiàn)在 switch
語句中的 case
標(biāo)簽中。
表達(dá)式模式代表的表達(dá)式會使用 Swift 標(biāo)準(zhǔn)庫中的 ~=
運(yùn)算符與輸入表達(dá)式的值進(jìn)行比較。如果 ~=
運(yùn)算符返回 true
,則匹配成功。默認(rèn)情況下,~=
運(yùn)算符使用 ==
運(yùn)算符來比較兩個相同類型的值。它也可以將一個整型數(shù)值與一個 Range
實(shí)例中的一段整數(shù)區(qū)間做匹配,正如下面這個例子所示:
let point = (1, 2)
switch point {
case (0, 0):
print("(0, 0) is at the origin.")
case (-2...2, -2...2):
print("(\(point.0), \(point.1)) is near the origin.")
default:
print("The point is at (\(point.0), \(point.1)).")
}
// 打印“(1, 2) is near the origin.”
你可以重載 ~=
運(yùn)算符來提供自定義的表達(dá)式匹配行為。比如你可以重寫上面的例子,將 point
表達(dá)式與字符串形式表示的點(diǎn)進(jìn)行比較。
// 重載 ~= 運(yùn)算符對字符串和整數(shù)進(jìn)行比較
func ~=(pattern: String, value: Int) -> Bool {
return pattern == "\(value)"
}
switch point {
case ("0", "0"):
print("(0, 0) is at the origin.")
default:
print("The point is at (\(point.0), \(point.1)).")
}
// 打印“The point is at (1, 2).”
表達(dá)式模式語法
expression-pattern
表達(dá)式模式 → 表達(dá)式