這里的教程為Swift官方教程中文版。

模式(Patterns)

模式代表單個值或者復(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、guardfor-in 語句的 case 條件句中使用這類模式。

模式語法

pattern

模式通配符模式 類型注解可選

模式標(biāo)識符模式 類型注解可選

模式值綁定模式

模式元組模式 類型注解可選

模式枚舉用例模式

模式可選模式

模式類型轉(zhuǎn)換模式

模式表達(dá)式模式

通配符模式(Wildcard Pattern)

通配符模式由一個下劃線(_)構(gòu)成,用于匹配并忽略任何值。當(dāng)你想忽略被匹配的值時(shí)可以使用該模式。例如,下面這段代碼在閉區(qū)間 1...3 中迭代,每次迭代都忽略該區(qū)間的當(dāng)前值:

for _ in 1...3 {
    // ...
}

通配符模式語法

wildcard-pattern

通配符模式_

標(biāo)識符模式(Identifier 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)識符

值綁定模式(Value-Binding Pattern)

值綁定模式把匹配到的值綁定給一個變量或常量。把匹配到的值綁定給常量時(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

值綁定模式var 模式 | let 模式

元組模式

元組模式是由逗號分隔的,具有零個或多個模式的列表,并由一對圓括號括起來。元組模式匹配相應(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-list

元組模式元素列表元組模式元素 | 元組模式元素 , 元組模式元素列表

tuple-pattern-element

元組模式元素模式

枚舉用例模式(Enumeration Case Pattern)

枚舉用例模式匹配現(xiàn)有的某個枚舉類型的某個用例。枚舉用例模式出現(xiàn)在 switch 語句中的 case 標(biāo)簽中,以及 ifwhile、guardfor-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 Pattern)

可選模式匹配包裝在一個 Optional(Wrapped) 或者 ExplicitlyUnwrappedOptional(Wrapped) 枚舉中的 Some(Wrapped) 用例中的值??蛇x模式由一個標(biāo)識符模式和緊隨其后的一個問號組成,可以像枚舉用例模式一樣使用。

由于可選模式是 OptionalImplicitlyUnwrappedOptional 枚舉用例模式的語法糖,下面兩種寫法是等效的:

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)換模式(Type-Casting Patterns)

有兩種類型轉(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

類型轉(zhuǎn)換模式is 模式 | as 模式

is-pattern

is 模式is 類型

as-pattern

as 模式模式 as 類型

表達(dá)式模式(Expression 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á)式

? 特性 泛型參數(shù) ?
?