模式
模式表示单个值或复合值的结构。例如,元组(1,2)的结构是两个元素的逗号分隔列表。由于模式表示值的结构而不是任何特定值,因此可以将它们与各种值匹配。例如,模式(x,y)匹配元组(1,2)和任何其他两元素元组。除了将模式与值匹配外,还可以提取部分或全部复合值,并将每个部分绑定到常量或变量名称。
在Swift中,有两种基本类型的模式:成功匹配任何类型值的那些模式,以及可能无法在运行时匹配指定值的模式。
第一种模式用于简单变量,常量和可选绑定中的值解构。这些包括通配符模式,标识符模式以及包含它们的任何值绑定或元组模式。您可以为这些模式指定类型注释,以限制它们仅匹配特定类型的值。
第二种模式用于全模式匹配,其中您尝试匹配的值可能不会在运行时存在。这些包括枚举案例模式,可选模式,表达式模式和类型转换模式。您可以在switch语句的case标签,do语句的catch子句或if,while,guard或for-in语句的case条件中使用这些模式。
pattern → wildcard-pattern-type-annotation-opt-
pattern → identifier-pattern-type-annotation-opt-
pattern → value-binding-pattern-
pattern → tuple-pattern-type-annotation-opt-
pattern → enum-case-pattern-
pattern → optional-pattern-
pattern → type-casting-pattern-
pattern → expression-pattern-
通配符模式
通配符模式匹配并忽略任何值,并由下划线(_)组成。 如果您不关心要匹配的值,请使用通配符模式。 例如,以下代码在闭合范围1 ... 3中迭代,忽略循环的每次迭代中范围的当前值:
for_in1...3 {
// Do something three times.
}
GRAMMAR OF A WILDCARD PATTERN
wildcard-pattern → _-
标识符模式
标识符模式匹配任何值并将匹配的值绑定到变量或常量名称。 例如,在下面的常量声明中,someValue是一个与Int类型的值42匹配的标识符模式:
let someValue = 42
当匹配成功时,值42被绑定(分配)为常数名称someValue。
当变量或常量声明左侧的模式是标识符模式时,标识符模式隐含地是值绑定模式的子模式
GRAMMAR OF AN IDENTIFIER PATTERN
identifier-pattern → identifier-
值绑定模式
值绑定模式将匹配值绑定到变量或常量名称。 将匹配值绑定到常量名称的值绑定模式以let关键字开头; 那些绑定到变量名称的变量以var关键字开头。
值绑定模式中的标识符模式将新的命名变量或常量绑定到它们的匹配值。 例如,可以分解元组的元素,并将每个元素的值绑定到相应的标识符模式。
let point = (3, 2)
switch point {
// Bind x and y to the elements of point.
case let (x, y):
print("The point is at (\(x), \(y)).")
}
// Prints "The point is at (3, 2)."
在上面的例子中,让我们分配给元组模式(x,y)中的每个标识符模式。 由于这种行为,切换案例的情况下let(x,y):和case(let x,let y):匹配相同的值
value-binding-pattern → var-pattern-let-pattern-
元组模式
元组模式是包含在括号中的零个或多个模式的逗号分隔列表。 元组模式匹配相应元组类型的值。
您可以通过使用类型注释来约束元组模式以匹配某些类型的元组类型。 例如,常量声明let(x,y):(Int,Int)=(1,2)中的元组模式(x,y):(Int,Int)仅匹配两个元素都是类型的元组类型诠释。
当元组模式用作for-in语句或变量或常量声明中的模式时,它只能包含通配符模式,标识符模式,可选模式或包含这些模式的其他元组模式。 例如,以下代码无效,因为元组模式(x,0)中的元素0是表达式模式:
let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]
// This code isn't valid.
for (x, 0) inpoints {
/* ... */
}
包含单个元素的元组模式周围的括号不起作用。 该模式匹配该单个元素类型的值。 例如,以下内容是等同的:
let a = 2// a: Int = 2
let (a) = 2// a: Int = 2
let (a): Int = 2// a: Int = 2
GRAMMAR OF A TUPLE PATTERN
tuple-pattern → (-tuple-pattern-element-list-opt-)-
tuple-pattern-element-list → tuple-pattern-element-tuple-pattern-element-,-tuple-pattern-element-list-
tuple-pattern-element → pattern-identifier-:-pattern-
枚举案例模式
枚举大小写模式匹配现有枚举类型的大小写。 枚举案例模式出现在switch语句的case标签和if,while,guard和for-in语句的case条件中。
如果您试图匹配的枚举类型具有任何关联值,则相应的枚举大小写模式必须指定一个元组模式,其中包含每个关联值的一个元素。 有关使用switch语句来匹配包含关联值的枚举个案的示例,请参阅关联值
enum-case-pattern → type-identifier-opt-.-enum-case-name-tuple-pattern-opt-
可选模式
可选模式匹配包装在可选<Wrapped>枚举的某个(Wrapped)情况下的值。 可选模式由标识符模式组成,后面紧跟着一个问号,并与枚举案例模式出现在相同的位置。
由于可选模式是可选枚举案例模式的语法糖,因此以下内容是等价的:
let someOptional: Int? = 42
// Match using an enumeration case pattern.
if case .some(letx) = someOptional {
print(x)
}
// Match using an optional pattern.
if case let x? = someOptional {
print(x)
}
可选模式提供了一种方便的方法,用于在for-in语句中迭代可选值的数组,只对非零元素执行循环体。
let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
// Match only non-nil values.
for caseletnumber? in arrayOfOptionalInts {
print("Found a \(number)")
}
// Found a 2
// Found a 3
// Found a 5
GRAMMAR OF AN OPTIONAL PATTERN
optional-pattern → identifier-pattern-?-
类型铸造模式
有两种类型转换模式,is模式和as模式。is模式只出现在switch语句的case标签中。
istype
patternastype
如果运行时该值的类型与is模式的右侧(或该类型的子类)中指定的类型相同,则该模式会匹配一个值。 is模式的行为与is操作符相同,它们都执行类型转换,但丢弃返回的类型。
如果运行时该值的类型与as模式右侧或该类型的子类中指定的类型相同,则as模式匹配值。 如果匹配成功,则将匹配值的类型转换为as模式右侧指定的模式。
有关使用switch语句将值与is和as模式进行匹配的示例,请参见对Any和AnyObject进行类型强制转换
type-casting-pattern → is-pattern-as-pattern-
is-pattern → is-type-
as-pattern → pattern-as-type-
表达式模式
表达式模式表示表达式的值。 表达式模式只出现在switch语句的case标签中。
使用Swift标准库?=运算符将表达式模式表示的表达式与输入表达式的值进行比较。 如果?=运算符返回true,则匹配成功。 默认情况下,?=运算符使用==运算符比较相同类型的两个值。它也可以通过检查值是否包含在范围内来匹配值和值的范围,如以下示例所示。
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)).")
}
// Prints "(1, 2) is near the origin."
您可以重载?=运算符以提供自定义表达式匹配行为。 例如,您可以重写上面的示例以将点表达式与点的字符串表示形式进行比较。
// Overload the ~= operator to match a string with an integer.
// 将~=运算符重载以使字符串与整数匹配
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)).")
}
// Prints "The point is at (1, 2)."
GRAMMAR OF AN EXPRESSION PATTERN
expression-pattern → expression-