finally adjust

This commit is contained in:
梁杰
2015-08-02 22:12:05 +08:00
parent 15321c7a74
commit 2044f4667f
37 changed files with 1923 additions and 1668 deletions

View File

@ -1,5 +1,10 @@
> 1.0
> 翻译:[numbbbbb](https://github.com/numbbbbb) > 翻译:[numbbbbb](https://github.com/numbbbbb)
> 校对:[yeahdongcn](https://github.com/yeahdongcn), [xtymichael](https://github.com/xtymichael) > 校对:[yeahdongcn](https://github.com/yeahdongcn)
> 2.0
> 翻译+校对:[xtymichael](https://github.com/xtymichael)
# 关于 Swift # 关于 Swift
----------------- -----------------

View File

@ -1,6 +1,10 @@
> 翻译:[numbbbbb](https://github.com/numbbbbb), [xtymichael](https://github.com/xtymichael) > 1.0
> 翻译:[numbbbbb](https://github.com/numbbbbb)
> 校对:[shinyzhu](https://github.com/shinyzhu), [stanzhai](https://github.com/stanzhai) > 校对:[shinyzhu](https://github.com/shinyzhu), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[xtymichael](https://github.com/xtymichael)
# Swift 初见 # Swift 初见
--- ---
@ -27,7 +31,7 @@ print("Hello, world")
> 注意: > 注意:
> 为了获得最好的体验,在 Xcode 当中使用代码预览功能。代码预览功能可以让你编辑代码并实时看到运行结果。 > 为了获得最好的体验,在 Xcode 当中使用代码预览功能。代码预览功能可以让你编辑代码并实时看到运行结果。
> <a href="https://github.com/numbbbbb/the-swift-programming-language-in-chinese/raw/gh-pages/source/chapter1/GuidedTour.playground.zip">下载Playground</a> > <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.playground.zip">下载Playground</a>
<a name="simple_values"></a> <a name="simple_values"></a>
## 简单值 ## 简单值

View File

@ -1,6 +1,10 @@
> 翻译:[numbbbbb](https://github.com/numbbbbb), [lyuka](https://github.com/lyuka), [JaySurplus](https://github.com/JaySurplus), [xtymichael](https://github.com/xtymichael) > 1.0
> 翻译:[numbbbbb](https://github.com/numbbbbb), [lyuka](https://github.com/lyuka), [JaySurplus](https://github.com/JaySurplus)
> 校对:[lslxdx](https://github.com/lslxdx) > 校对:[lslxdx](https://github.com/lslxdx)
> 2.0
> [xtymichael](https://github.com/xtymichael)
# 基础部分 # 基础部分
----------------- -----------------
@ -99,6 +103,12 @@ var welcomeMessage: String
welcomeMessage = "Hello" welcomeMessage = "Hello"
``` ```
你可以在一行中定义多个同样类型的变量,用逗号分割,并在最后一个变量名之后添加类型标注:
```swift
var red, green, blue: Double
```
> 注意: > 注意:
一般来说你很少需要写类型标注。如果你在声明常量或者变量的时候赋了一个初始值Swift可以推断出这个常量或者变量的类型请参考[类型安全和类型推断](#type_safety_and_type_inference)。在上面的例子中,没有给`welcomeMessage`赋初始值,所以变量`welcomeMessage`的类型是通过一个类型标注指定的,而不是通过初始值推断的。 一般来说你很少需要写类型标注。如果你在声明常量或者变量的时候赋了一个初始值Swift可以推断出这个常量或者变量的类型请参考[类型安全和类型推断](#type_safety_and_type_inference)。在上面的例子中,没有给`welcomeMessage`赋初始值,所以变量`welcomeMessage`的类型是通过一个类型标注指定的,而不是通过初始值推断的。
@ -165,7 +175,7 @@ print("The current value of friendlyWelcome is \(friendlyWelcome)")
``` ```
> 注意: > 注意:
字符串插值所有可用的选项,请参考[字符串插值](03_Strings_and_Characters.html#string_interpolation)。 字符串插值所有可用的选项,请参考[字符串插值](./03_Strings_and_Characters.html#string_interpolation)。
<a name="comments"></a> <a name="comments"></a>
## 注释 ## 注释
@ -369,7 +379,7 @@ let twoThousandAndOne = twoThousand + UInt16(one)
现在两个数字的类型都是`UInt16`,可以进行相加。目标常量`twoThousandAndOne`的类型被推断为`UInt16`,因为它是两个`UInt16`值的和。 现在两个数字的类型都是`UInt16`,可以进行相加。目标常量`twoThousandAndOne`的类型被推断为`UInt16`,因为它是两个`UInt16`值的和。
`SomeType(ofInitialValue)`是调用 Swift 构造器并传入一个初始值的默认方法。在语言内部,`UInt16`有一个构造器,可以接受一个`UInt8`类型的值,所以这个构造器可以用现有的`UInt8`来创建一个新的`UInt16`。注意,你并不能传入任意类型的值,只能传入`UInt16`内部有对应构造器的值。不过你可以扩展现有的类型来让它可以接收其他类型的值(包括自定义类型),请参考[扩展](20_Extensions.html)。 `SomeType(ofInitialValue)`是调用 Swift 构造器并传入一个初始值的默认方法。在语言内部,`UInt16`有一个构造器,可以接受一个`UInt8`类型的值,所以这个构造器可以用现有的`UInt8`来创建一个新的`UInt16`。注意,你并不能传入任意类型的值,只能传入`UInt16`内部有对应构造器的值。不过你可以扩展现有的类型来让它可以接收其他类型的值(包括自定义类型),请参考[扩展](./20_Extensions.html)。
<a name="integer_and_floating_point_conversion"></a> <a name="integer_and_floating_point_conversion"></a>
### 整数和浮点数转换 ### 整数和浮点数转换
@ -440,7 +450,7 @@ if turnipsAreDelicious {
// 输出 "Eww, turnips are horrible." // 输出 "Eww, turnips are horrible."
``` ```
条件语句,例如`if`,请参考[控制流](05_Control_Flow.html)。 条件语句,例如`if`,请参考[控制流](./05_Control_Flow.html)。
如果你在需要使用`Bool`类型的地方使用了非布尔值Swift 的类型安全机制会报错。下面的例子会报告一个编译时错误: 如果你在需要使用`Bool`类型的地方使用了非布尔值Swift 的类型安全机制会报错。下面的例子会报告一个编译时错误:
@ -460,7 +470,7 @@ if i == 1 {
} }
``` ```
`i == 1`的比较结果是`Bool`类型,所以第二个例子可以通过类型检查。类似`i == 1`这样的比较,请参考[基本操作符](05_Control_Flow.html)。 `i == 1`的比较结果是`Bool`类型,所以第二个例子可以通过类型检查。类似`i == 1`这样的比较,请参考[基本操作符](./05_Control_Flow.html)。
和 Swift 中的其他类型安全的例子一样,这个方法可以避免错误并保证这块代码的意图总是清晰的。 和 Swift 中的其他类型安全的例子一样,这个方法可以避免错误并保证这块代码的意图总是清晰的。
@ -522,10 +532,10 @@ print("The status message is \(http200Status.description)")
// 输出 "The status message is OK" // 输出 "The status message is OK"
``` ```
作为函数返回值时,元组非常有用。一个用来获取网页的函数可能会返回一个`(Int, String)`元组来描述是否获取成功。和只能返回一个类型的值比较起来,一个包含两个不同类型值的元组可以让函数的返回信息更有用。请参考[函数参数与返回值](06_Functions.html#Function_Parameters_and_Return_Values)。 作为函数返回值时,元组非常有用。一个用来获取网页的函数可能会返回一个`(Int, String)`元组来描述是否获取成功。和只能返回一个类型的值比较起来,一个包含两个不同类型值的元组可以让函数的返回信息更有用。请参考[函数参数与返回值](./06_Functions.html#Function_Parameters_and_Return_Values)。
> 注意: > 注意:
元组在临时组织值的时候很有用,但是并不适合创建复杂的数据结构。如果你的数据结构并不是临时使用,请使用类或者结构体而不是元组。请参考[类和结构体](09_Classes_and_Structures.html)。 元组在临时组织值的时候很有用,但是并不适合创建复杂的数据结构。如果你的数据结构并不是临时使用,请使用类或者结构体而不是元组。请参考[类和结构体](./09_Classes_and_Structures.html)。
<a name="optionals"></a> <a name="optionals"></a>
## 可选类型 ## 可选类型
@ -608,7 +618,7 @@ if convertedNumber != nil {
<a name="optional_binding"></a> <a name="optional_binding"></a>
### 可选绑定 ### 可选绑定
使用可选绑定optional binding来判断可选类型是否包含值如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在`if`和`while`语句中来对可选类型的值进行判断并把值赋给一个常量或者变量。`if`和`while`语句,请参考[控制流](05_Control_Flow.html)。 使用可选绑定optional binding来判断可选类型是否包含值如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在`if`和`while`语句中来对可选类型的值进行判断并把值赋给一个常量或者变量。`if`和`while`语句,请参考[控制流](./05_Control_Flow.html)。
像下面这样在`if`语句中写一个可选绑定: 像下面这样在`if`语句中写一个可选绑定:
@ -654,7 +664,7 @@ if let constantName = someOptional, anotherConstantName = someOtherOptional {
这种类型的可选状态被定义为隐式解析可选类型implicitly unwrapped optionals。把想要用作可选的类型的后面的问号`String?`)改成感叹号(`String!`)来声明一个隐式解析可选类型。 这种类型的可选状态被定义为隐式解析可选类型implicitly unwrapped optionals。把想要用作可选的类型的后面的问号`String?`)改成感叹号(`String!`)来声明一个隐式解析可选类型。
当可选类型被第一次赋值之后就可以确定之后一直有值的时候,隐式解析可选类型非常有用。隐式解析可选类型主要被用在 Swift 中类的构造过程中,请参考[类实例之间的循环强引用](16_Automatic_Reference_Counting.html#strong_reference_cycles_between_class_instances)。 当可选类型被第一次赋值之后就可以确定之后一直有值的时候,隐式解析可选类型非常有用。隐式解析可选类型主要被用在 Swift 中类的构造过程中,请参考[无主引用以及隐式解析可选属性](./16_Automatic_Reference_Counting.html#unowned_references_and_implicitly_unwrapped_optional_properties)。
一个隐式解析可选类型其实就是一个普通的可选类型,但是可以被当做非可选类型来使用,并不需要每次都使用解析来获取可选值。下面的例子展示了可选类型`String`和隐式解析可选类型`String`之间的区别: 一个隐式解析可选类型其实就是一个普通的可选类型,但是可以被当做非可选类型来使用,并不需要每次都使用解析来获取可选值。下面的例子展示了可选类型`String`和隐式解析可选类型`String`之间的区别:
@ -740,7 +750,7 @@ do {
如果没有错误被抛出, `eatASandwich()`函数会被调用。如果一个符合`Error.OutOfCleanDishes`的错误被抛出,`washDishes`函数会被调用。如果一个符合`Error.MissingIngredients`的错误被抛出,`buyGroceries(_:)`函数会被调用并传递相关被`catch`所捕捉到的`[String]`值。 如果没有错误被抛出, `eatASandwich()`函数会被调用。如果一个符合`Error.OutOfCleanDishes`的错误被抛出,`washDishes`函数会被调用。如果一个符合`Error.MissingIngredients`的错误被抛出,`buyGroceries(_:)`函数会被调用并传递相关被`catch`所捕捉到的`[String]`值。
抛出,捕捉,传递错误会在[错误处理](../chapter2/18_Error_Handling.html)章节详细说明。 抛出,捕捉,传递错误会在[错误处理](./18_Error_Handling.html)章节详细说明。
<a name="assertions"></a> <a name="assertions"></a>
## 断言 ## 断言
@ -777,7 +787,7 @@ assert(age >= 0)
* 需要给函数传入一个值,但是非法的值可能导致函数不能正常执行。 * 需要给函数传入一个值,但是非法的值可能导致函数不能正常执行。
* 一个可选值现在是`nil`,但是后面的代码运行需要一个非`nil`值。 * 一个可选值现在是`nil`,但是后面的代码运行需要一个非`nil`值。
请参考[下标脚本](12_Subscripts.html)和[函数](06_Functions.html)。 请参考[下标脚本](./12_Subscripts.html)和[函数](./06_Functions.html)。
> 注意: > 注意:
断言可能导致你的应用终止运行,所以你应当仔细设计你的代码来让非法条件不会出现。然而,在你的应用发布之前,有时候非法条件可能出现,这时使用断言可以快速发现问题。 断言可能导致你的应用终止运行,所以你应当仔细设计你的代码来让非法条件不会出现。然而,在你的应用发布之前,有时候非法条件可能出现,这时使用断言可以快速发现问题。

View File

@ -1,6 +1,9 @@
> 1.0
> 翻译:[XieLingWang](https://github.com/xielingwang)
> 校对:[EvilCome](https://github.com/Evilcome)
> 翻译:[XieLingWang](https://github.com/xielingwang), [JackAlan](https://github.com/AlanMelody) > 2.0
> 校对:[EvilCome](https://github.com/Evilcome), [JackAlan](https://github.com/AlanMelody) > 翻译+校对:[JackAlan](https://github.com/AlanMelody)
# 基本运算符 # 基本运算符
----------------- -----------------
@ -19,11 +22,11 @@
运算符是检查、改变、合并值的特殊符号或短语。例如,加号`+`将两个数相加(如`let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符`&&`(如`if enteredDoorCode && passedRetinaScan`),或让 i 值加1的便捷自增运算符`++i`等。 运算符是检查、改变、合并值的特殊符号或短语。例如,加号`+`将两个数相加(如`let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符`&&`(如`if enteredDoorCode && passedRetinaScan`),或让 i 值加1的便捷自增运算符`++i`等。
Swift 支持大部分标准 C 语言的运算符,且改进许多特性来减少常规编码错误。如:赋值符(`=`)不返回值,以防止把想要判断相等运算符(`==`)的地方写成赋值符导致的错误。算术运算符(`+``-``*``/``%`等)会检测并不允许值溢出,以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果。当然允许你使用 Swift 的溢出运算符来实现溢出。详情参见[溢出运算符](24_Advanced_Operators.html#overflow_operators)。 Swift 支持大部分标准 C 语言的运算符,且改进许多特性来减少常规编码错误。如:赋值符(`=`)不返回值,以防止把想要判断相等运算符(`==`)的地方写成赋值符导致的错误。算术运算符(`+``-``*``/``%`等)会检测并不允许值溢出,以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果。当然允许你使用 Swift 的溢出运算符来实现溢出。详情参见[溢出运算符](./24_Advanced_Operators.html#overflow_operators)。
区别于 C 语言,在 Swift 中你可以对浮点数进行取余运算(`%`Swift 还提供了 C 语言没有的表达两数之间的值的区间运算符(`a..<b``a...b`),这方便我们表达一个区间内的数值。 区别于 C 语言,在 Swift 中你可以对浮点数进行取余运算(`%`Swift 还提供了 C 语言没有的表达两数之间的值的区间运算符(`a..<b``a...b`),这方便我们表达一个区间内的数值。
本章节只描述了 Swift 中的基本运算符,[高级运算符](24_Advanced_Operators.html)包含了高级运算符,及如何自定义运算符,及如何进行自定义类型的运算符重载。 本章节只描述了 Swift 中的基本运算符,[高级运算符](./24_Advanced_Operators.html)包含了高级运算符,及如何自定义运算符,及如何进行自定义类型的运算符重载。
<a name="terminology"></a> <a name="terminology"></a>
## 术语 ## 术语
@ -77,7 +80,7 @@ Swift 中所有数值类型都支持了基本的四则算术运算:
与 C 语言和 Objective-C 不同的是Swift 默认情况下不允许在数值运算中出现溢出情况。但是你可以使用 Swift 的溢出运算符来实现溢出运算(如`a &+ b`)。详情参见[溢出运算符](24_Advanced_Operators.html#overflow_operators)。 与 C 语言和 Objective-C 不同的是Swift 默认情况下不允许在数值运算中出现溢出情况。但是你可以使用 Swift 的溢出运算符来实现溢出运算(如`a &+ b`)。详情参见[溢出运算符](./24_Advanced_Operators.html#overflow_operators)。
加法运算符也可用于`String`的拼接: 加法运算符也可用于`String`的拼接:
@ -215,7 +218,7 @@ Swift 中所有数值类型都支持了基本的四则算术运算:
- 小于等于(`a <= b` - 小于等于(`a <= b`
> 注意: > 注意:
Swift 也提供恒等`===`和不恒等`!==`这两个比较符来判断两个对象是否引用同一个对象实例。更多细节在[类与结构](09_Classes_and_Structures.html)。 Swift 也提供恒等`===`和不恒等`!==`这两个比较符来判断两个对象是否引用同一个对象实例。更多细节在[类与结构](./09_Classes_and_Structures.html)。
每个比较运算都返回了一个标识表达式是否成立的布尔值: 每个比较运算都返回了一个标识表达式是否成立的布尔值:
@ -240,7 +243,7 @@ Swift 也提供恒等`===`和不恒等`!==`这两个比较符来判断两个对
// 输出 "hello, world", 因为 `name` 就是等于 "world" // 输出 "hello, world", 因为 `name` 就是等于 "world"
关于`if`语句,请看[控制流](05_Control_Flow.html)。 关于`if`语句,请看[控制流](./05_Control_Flow.html)。
<a name="ternary_conditional_operator"></a> <a name="ternary_conditional_operator"></a>
## 三目运算符(Ternary Conditional Operator) ## 三目运算符(Ternary Conditional Operator)
@ -335,7 +338,7 @@ Swift 提供了两个方便表达一个区间的值的运算符。
// 5 * 5 = 25 // 5 * 5 = 25
关于`for-in`,请看[控制流](05_Control_Flow.html)。 关于`for-in`,请看[控制流](./05_Control_Flow.html)。
### 半开区间运算符 ### 半开区间运算符
@ -356,7 +359,7 @@ Swift 提供了两个方便表达一个区间的值的运算符。
// 4 个人叫 Jack // 4 个人叫 Jack
数组有4个元素`0..<count`只数到3(最后一个元素的下标)因为它是半开区间关于数组请查阅[数组](04_Collection_Types.html#arrays) 数组有4个元素`0..<count`只数到3(最后一个元素的下标)因为它是半开区间关于数组请查阅[数组](./04_Collection_Types.html#arrays)
<a name="logical_operators"></a> <a name="logical_operators"></a>
## 逻辑运算 ## 逻辑运算
@ -434,10 +437,10 @@ Swift 提供了两个方便表达一个区间的值的运算符。
如果我们输入了正确的密码并通过了视网膜扫描; 或者我们有一把有效的钥匙; 又或者我们知道紧急情况下重置的密码,我们就能把门打开进入。 如果我们输入了正确的密码并通过了视网膜扫描; 或者我们有一把有效的钥匙; 又或者我们知道紧急情况下重置的密码,我们就能把门打开进入。
前两种情况,我们都不满足,所以前两个简单逻辑的结果是`false`,但是我们是知道紧急情况下重置的密码的,所以整个复杂表达式的值还是`true` 前两种情况,我们都不满足,所以前两个简单逻辑的结果是`false`,但是我们是知道紧急情况下重置的密码的,所以整个复杂表达式的值还是`true`
>注意: >注意:
Swift 逻辑操作符`&&``||`是左结合的,这意味着拥有多元逻辑操作符的复合表达式优先计算最左边的子表达式。 Swift 逻辑操作符`&&``||`是左结合的,这意味着拥有多元逻辑操作符的复合表达式优先计算最左边的子表达式。
### 使用括号来明确优先级 ### 使用括号来明确优先级

View File

@ -1,11 +1,15 @@
> 翻译:[wh1100717](https://github.com/wh1100717) > 1.0
> 校对:[Hawstein](https://github.com/Hawstein) > 翻译:[wh1100717](https://github.com/wh1100717)
> 校对:[Hawstein](https://github.com/Hawstein)
# 字符串和字符Strings and Characters
--- > 2.0
> 翻译+校对:[DianQK](https://github.com/DianQK)
本页包含内容:
# 字符串和字符Strings and Characters
---
本页包含内容:
- [字符串字面量](#string_literals) - [字符串字面量](#string_literals)
- [初始化空字符串](#initializing_an_empty_string) - [初始化空字符串](#initializing_an_empty_string)
- [字符串可变性](#string_mutability) - [字符串可变性](#string_mutability)
@ -17,59 +21,59 @@
- [计算字符数量](#counting_characters) - [计算字符数量](#counting_characters)
- [访问和修改字符串](#accessing_and_modifying_a_string) - [访问和修改字符串](#accessing_and_modifying_a_string)
- [比较字符串](#comparing_strings) - [比较字符串](#comparing_strings)
- [字符串的 Unicode 表示形式](#unicode_representations_of_strings) - [字符串的 Unicode 表示形式](#unicode_representations_of_strings)
`String`是例如"hello, world""albatross"这样的有序的`Character`(字符)类型的值的集合,通过`String`类型来表示。 `String`是例如"hello, world""albatross"这样的有序的`Character`(字符)类型的值的集合,通过`String`类型来表示。
Swift 的`String``Character`类型提供了一个快速的,兼容 Unicode 的方式来处理代码中的文本。 Swift 的`String``Character`类型提供了一个快速的,兼容 Unicode 的方式来处理代码中的文本。
创建和操作字符串的语法与 C 语言中字符串操作相似,轻量并且易读。 创建和操作字符串的语法与 C 语言中字符串操作相似,轻量并且易读。
字符串连接操作只需要简单地通过`+`符号将两个字符串相连即可。 字符串连接操作只需要简单地通过`+`符号将两个字符串相连即可。
与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。 与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。
尽管语法简易,但`String`类型是一种快速、现代化的字符串实现。 尽管语法简易,但`String`类型是一种快速、现代化的字符串实现。
每一个字符串都是由编码无关的 Unicode 字符组成,并支持访问字符的多种 Unicode 表示形式representations 每一个字符串都是由编码无关的 Unicode 字符组成,并支持访问字符的多种 Unicode 表示形式representations
你也可以在常量、变量、字面量和表达式中进行字符串插值操作,这可以帮助你轻松创建用于展示、存储和打印的自定义字符串。 你也可以在常量、变量、字面量和表达式中进行字符串插值操作,这可以帮助你轻松创建用于展示、存储和打印的自定义字符串。
> 注意: > 注意:
> Swift 的`String`类型与 Foundation `NSString`类进行了无缝桥接。就像 [AnyObject](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html#//apple_ref/doc/uid/TP40014097-CH22-ID343) 中提到的一样,在使用 Cocoa 中的 Foundation 框架时,您可以将创建的任何字符串的值转换成`NSString`,并调用任意的`NSString` API。您也可以在任意要求传入`NSString`实例作为参数的 API 中用`String`类型的值代替。 > Swift 的`String`类型与 Foundation `NSString`类进行了无缝桥接。就像 [`AnyObject`类型](./20_Type_Casting.html#anyobject) 中提到的一样,在使用 Cocoa 中的 Foundation 框架时,您可以将创建的任何字符串的值转换成`NSString`,并调用任意的`NSString` API。您也可以在任意要求传入`NSString`实例作为参数的 API 中用`String`类型的值代替。
> 更多关于在 Foundation 和 Cocoa 中使用`String`的信息请查看 *[Using Swift with Cocoa and Objective-C](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)*。 > 更多关于在 Foundation 和 Cocoa 中使用`String`的信息请查看 *[Using Swift with Cocoa and Objective-C](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)*。
<a name="string_literals"></a> <a name="string_literals"></a>
## 字符串字面量String Literals ## 字符串字面量String Literals
您可以在您的代码中包含一段预定义的字符串值作为字符串字面量。字符串字面量是由双引号 ("") 包裹着的具有固定顺序的文本字符集。 您可以在您的代码中包含一段预定义的字符串值作为字符串字面量。字符串字面量是由双引号 ("") 包裹着的具有固定顺序的文本字符集。
字符串字面量可以用于为常量和变量提供初始值: 字符串字面量可以用于为常量和变量提供初始值:
```let someString = "Some string literal value"``` ```let someString = "Some string literal value"```
注意`someString`常量通过字符串字面量进行初始化Swift 会推断该常量为`String`类型。 注意`someString`常量通过字符串字面量进行初始化Swift 会推断该常量为`String`类型。
> 注意: > 注意:
> 更多关于在字面量的特殊字符,请查看 [Special Characters in String Literals](#special_characters_in_string_literals) 。 > 更多关于在字面量的特殊字符,请查看 [Special Characters in String Literals](#special_characters_in_string_literals) 。
<a name="initializing_an_empty_string"></a> <a name="initializing_an_empty_string"></a>
## 初始化空字符串 (Initializing an Empty String) ## 初始化空字符串 (Initializing an Empty String)
要创建一个空字符串作为初始值,可以将空的字符串字面量赋值给变量,也可以初始化一个新的`String`实例: 要创建一个空字符串作为初始值,可以将空的字符串字面量赋值给变量,也可以初始化一个新的`String`实例:
```swift ```swift
var emptyString = "" // 空字符串字面量 var emptyString = "" // 空字符串字面量
var anotherEmptyString = String() // 初始化方法 var anotherEmptyString = String() // 初始化方法
// 两个字符串均为空并等价。 // 两个字符串均为空并等价。
``` ```
您可以通过检查其`Boolean`类型的`isEmpty`属性来判断该字符串是否为空: 您可以通过检查其`Boolean`类型的`isEmpty`属性来判断该字符串是否为空:
```swift ```swift
if emptyString.isEmpty { if emptyString.isEmpty {
print("Nothing to see here") print("Nothing to see here")
} }
// 打印输出:"Nothing to see here" // 打印输出:"Nothing to see here"
``` ```
<a name="string_mutability"></a> <a name="string_mutability"></a>
## 字符串可变性 (String Mutability) ## 字符串可变性 (String Mutability)
您可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改: 您可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改:
```swift ```swift
var variableString = "Horse" var variableString = "Horse"
variableString += " and carriage" variableString += " and carriage"
@ -77,33 +81,33 @@ variableString += " and carriage"
let constantString = "Highlander" let constantString = "Highlander"
constantString += " and another Highlander" constantString += " and another Highlander"
// 这会报告一个编译错误 (compile-time error) - 常量不可以被修改。 // 这会报告一个编译错误 (compile-time error) - 常量不可以被修改。
``` ```
> 注意: > 注意:
> 在 Objective-C 和 Cocoa 中,您需要通过选择两个不同的类(`NSString`和`NSMutableString`)来指定该字符串是否可以被修改。 > 在 Objective-C 和 Cocoa 中,您需要通过选择两个不同的类(`NSString`和`NSMutableString`)来指定该字符串是否可以被修改。
<a name="strings_are_value_types"></a> <a name="strings_are_value_types"></a>
## 字符串是值类型Strings Are Value Types ## 字符串是值类型Strings Are Value Types
Swift 的`String`类型是值类型。 Swift 的`String`类型是值类型。
如果您创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。 如果您创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。
任何情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值操作。 任何情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值操作。
值类型在 [结构体和枚举是值类型](09_Classes_and_Structures.html#structures_and_enumerations_are_value_types) 中进行了详细描述。 值类型在 [结构体和枚举是值类型](./09_Classes_and_Structures.html#structures_and_enumerations_are_value_types) 中进行了详细描述。
> 注意: > 注意:
> 与 Cocoa 中的`NSString`不同,当您在 Cocoa 中创建了一个`NSString`实例,并将其传递给一个函数/方法,或者赋值给一个变量,您传递或赋值的是该`NSString`实例的一个引用,除非您特别要求进行值拷贝,否则字符串不会生成新的副本来进行赋值操作。 > 与 Cocoa 中的`NSString`不同,当您在 Cocoa 中创建了一个`NSString`实例,并将其传递给一个函数/方法,或者赋值给一个变量,您传递或赋值的是该`NSString`实例的一个引用,除非您特别要求进行值拷贝,否则字符串不会生成新的副本来进行赋值操作。
Swift 默认字符串拷贝的方式保证了在函数/方法中传递的是字符串的值。 Swift 默认字符串拷贝的方式保证了在函数/方法中传递的是字符串的值。
很明显无论该值来自于哪里,都是您独自拥有的。 很明显无论该值来自于哪里,都是您独自拥有的。
您可以放心您传递的字符串本身不会被更改。 您可以放心您传递的字符串本身不会被更改。
在实际编译时Swift 编译器会优化字符串的使用,使实际的复制只发生在绝对必要的情况下,这意味着您将字符串作为值类型的同时可以获得极高的性能。 在实际编译时Swift 编译器会优化字符串的使用,使实际的复制只发生在绝对必要的情况下,这意味着您将字符串作为值类型的同时可以获得极高的性能。
<a name="working_with_characters"></a> <a name="working_with_characters"></a>
## 使用字符Working with Characters ## 使用字符Working with Characters
您可通过`for-in`循环来遍历字符串中的`characters`属性来获取每一个字符的值: 您可通过`for-in`循环来遍历字符串中的`characters`属性来获取每一个字符的值:
```swift ```swift
for character in "Dog!🐶".characters { for character in "Dog!🐶".characters {
print(character) print(character)
@ -113,12 +117,12 @@ for character in "Dog!🐶".characters {
// g // g
// ! // !
// 🐶 // 🐶
``` ```
for-in 循环在 [For Loops](05_Control_Flow.html#for_loops) 中进行了详细描述。 for-in 循环在 [For Loops](./05_Control_Flow.html#for_loops) 中进行了详细描述。
另外,通过标明一个`Character`类型并用字符字面量进行赋值,可以建立一个独立的字符常量或变量: 另外,通过标明一个`Character`类型并用字符字面量进行赋值,可以建立一个独立的字符常量或变量:
```swift ```swift
let exclamationMark: Charater = "!" let exclamationMark: Charater = "!"
``` ```
@ -131,96 +135,96 @@ print(catString)
// 打印输出:"Cat!🐱" // 打印输出:"Cat!🐱"
``` ```
<a name="concatenating_strings_and_characters"></a> <a name="concatenating_strings_and_characters"></a>
## 连接字符串和字符 (Concatenating Strings and Characters) ## 连接字符串和字符 (Concatenating Strings and Characters)
字符串可以通过加法运算符(`+`)相加在一起(或称“连接”)创建一个新的字符串: 字符串可以通过加法运算符(`+`)相加在一起(或称“连接”)创建一个新的字符串:
```swift ```swift
let string1 = "hello" let string1 = "hello"
let string2 = " there" let string2 = " there"
var welcome = string1 + string2 var welcome = string1 + string2
// welcome 现在等于 "hello there" // welcome 现在等于 "hello there"
``` ```
您也可以通过加法赋值运算符 (`+=`) 将一个字符串添加到一个已经存在字符串变量上: 您也可以通过加法赋值运算符 (`+=`) 将一个字符串添加到一个已经存在字符串变量上:
```swift ```swift
var instruction = "look over" var instruction = "look over"
instruction += string2 instruction += string2
// instruction 现在等于 "look over there" // instruction 现在等于 "look over there"
``` ```
您可以用`append`方法将一个字符附加到一个字符串变量的尾部: 您可以用`append`方法将一个字符附加到一个字符串变量的尾部:
```swift ```swift
let exclamationMark: Character = "!" let exclamationMark: Character = "!"
welcome.append(exclamationMark) welcome.append(exclamationMark)
// welcome 现在等于 "hello there!" // welcome 现在等于 "hello there!"
``` ```
> 注意: > 注意:
> 您不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。 > 您不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。
<a name="string_interpolation"></a> <a name="string_interpolation"></a>
## 字符串插值 (String Interpolation) ## 字符串插值 (String Interpolation)
字符串插值是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式。 字符串插值是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式。
您插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中: 您插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中:
```swift ```swift
let multiplier = 3 let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message 是 "3 times 2.5 is 7.5" // message 是 "3 times 2.5 is 7.5"
``` ```
在上面的例子中,`multiplier`作为`\(multiplier)`被插入到一个字符串字面量中。 在上面的例子中,`multiplier`作为`\(multiplier)`被插入到一个字符串字面量中。
当创建字符串执行插值计算时此占位符会被替换为`multiplier`实际的值。 当创建字符串执行插值计算时此占位符会被替换为`multiplier`实际的值。
`multiplier`的值也作为字符串中后面表达式的一部分。 `multiplier`的值也作为字符串中后面表达式的一部分。
该表达式计算`Double(multiplier) * 2.5`的值并将结果 (7.5) 插入到字符串中。 该表达式计算`Double(multiplier) * 2.5`的值并将结果 (7.5) 插入到字符串中。
在这个例子中,表达式写为`\(Double(multiplier) * 2.5)`并包含在字符串字面量中。 在这个例子中,表达式写为`\(Double(multiplier) * 2.5)`并包含在字符串字面量中。
> 注意: > 注意:
> 插值字符串中写在括号中的表达式不能包含非转义双引号 (`"`) 和反斜杠 (`\`),并且不能包含回车或换行符。 > 插值字符串中写在括号中的表达式不能包含非转义双引号 (`"`) 和反斜杠 (`\`),并且不能包含回车或换行符。
<a name="unicode"></a> <a name="unicode"></a>
## Unicode ## Unicode
Unicode 是一个国际标准,用于文本的编码和表示。 Unicode 是一个国际标准,用于文本的编码和表示。
它使您可以用标准格式表示来自任意语言几乎所有的字符,并能够对文本文件或网页这样的外部资源中的字符进行读写操作。 它使您可以用标准格式表示来自任意语言几乎所有的字符,并能够对文本文件或网页这样的外部资源中的字符进行读写操作。
Swift 的字符串和字符类型是完全兼容 Unicode 标准的。 Swift 的字符串和字符类型是完全兼容 Unicode 标准的。
<a name="unicode_scalars"></a> <a name="unicode_scalars"></a>
### Unicode 标量Unicode Scalars ### Unicode 标量Unicode Scalars
Swift 的`String`类型是基于 *Unicode 标量* 建立的。 Swift 的`String`类型是基于 *Unicode 标量* 建立的。
Unicode 标量是对应字符的唯一21位数字或者修饰符例如`U+0061`表示小写的拉丁字母(`LATIN SMALL LETTER A`)("`a`")`U+1F425`表示小鸡表情(`FRONT-FACING BABY CHICK`) ("`🐥`") Unicode 标量是对应字符的唯一21位数字或者修饰符例如`U+0061`表示小写的拉丁字母(`LATIN SMALL LETTER A`)("`a`")`U+1F425`表示小鸡表情(`FRONT-FACING BABY CHICK`) ("`🐥`")
> 注意: > 注意:
> Unicode *码位(code poing)* 的范围是`U+0000`到`U+D7FF`或者`U+E000`到`U+10FFFF`。Unicode 标量不包括 Unicode *代理项(surrogate pair)* 码位,其码位范围是`U+D800`到`U+DFFF`。 > Unicode *码位(code poing)* 的范围是`U+0000`到`U+D7FF`或者`U+E000`到`U+10FFFF`。Unicode 标量不包括 Unicode *代理项(surrogate pair)* 码位,其码位范围是`U+D800`到`U+DFFF`。
注意不是所有的21位 Unicode 标量都代表一个字符,因为有一些标量是保留给未来分配的。已经代表一个典型字符的标量都有自己的名字,例如上面例子中的`LATIN SMALL LETTER A``FRONT-FACING BABY CHICK` 注意不是所有的21位 Unicode 标量都代表一个字符,因为有一些标量是保留给未来分配的。已经代表一个典型字符的标量都有自己的名字,例如上面例子中的`LATIN SMALL LETTER A``FRONT-FACING BABY CHICK`
<a name="special_characters_in_string_literals"></a> <a name="special_characters_in_string_literals"></a>
### 字符串字面量的特殊字符 (Special Characters in String Literals) ### 字符串字面量的特殊字符 (Special Characters in String Literals)
字符串字面量可以包含以下特殊字符: 字符串字面量可以包含以下特殊字符:
* 转义字符`\0`(空字符)、`\\`(反斜线)、`\t`(水平制表符)、`\n`(换行符)、`\r`(回车符)、`\"`(双引号)、`\'`(单引号)。 * 转义字符`\0`(空字符)、`\\`(反斜线)、`\t`(水平制表符)、`\n`(换行符)、`\r`(回车符)、`\"`(双引号)、`\'`(单引号)。
* Unicode 标量,写成`\u{n}`(u为小写),其中`n`为任意一到八位十六进制数且可用的 Unicode 位码。 * Unicode 标量,写成`\u{n}`(u为小写),其中`n`为任意一到八位十六进制数且可用的 Unicode 位码。
下面的代码为各种特殊字符的使用示例。 下面的代码为各种特殊字符的使用示例。
`wiseWords`常量包含了两个双引号; `wiseWords`常量包含了两个双引号;
`dollarSign``blackHeart``sparklingHeart`常量演示了三种不同格式的 Unicode 标量: `dollarSign``blackHeart``sparklingHeart`常量演示了三种不同格式的 Unicode 标量:
```swift ```swift
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein" let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
// "Imageination is more important than knowledge" - Enistein // "Imageination is more important than knowledge" - Enistein
let dollarSign = "\u{24}" // $, Unicode 标量 U+0024 let dollarSign = "\u{24}" // $, Unicode 标量 U+0024
let blackHeart = "\u{2665}" // ♥, Unicode 标量 U+2665 let blackHeart = "\u{2665}" // ♥, Unicode 标量 U+2665
let sparklingHeart = "\u{1F496}" // 💖, Unicode 标量 U+1F496 let sparklingHeart = "\u{1F496}" // 💖, Unicode 标量 U+1F496
``` ```
<a name="extended_grapheme_clusters"></a> <a name="extended_grapheme_clusters"></a>
@ -262,22 +266,22 @@ let enclosedEAcute: Character = "\u{E9}\u{20DD}"
```swift ```swift
let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}" let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
// regionalIndicatorForUS 是 🇺🇸 // regionalIndicatorForUS 是 🇺🇸
``` ```
<a name="counting_characters"></a> <a name="counting_characters"></a>
## 计算字符数量 (Counting Characters) ## 计算字符数量 (Counting Characters)
调用字符串的`count`属性,就可以获取一个字符串的字符数量: 调用字符串的`count`属性,就可以获取一个字符串的字符数量:
```swift ```swift
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪" let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \(unusualMenagerie.characters.count) characters") print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
// 打印输出:"unusualMenagerie has 40 characters" // 打印输出:"unusualMenagerie has 40 characters"
``` ```
注意在 Swift 中,使用可拓展的字符群集作为字符来连接或改变字符串时,并不一定会更改字符串的字符数量。 注意在 Swift 中,使用可拓展的字符群集作为字符来连接或改变字符串时,并不一定会更改字符串的字符数量。
例如,如果你用四个字符的单词 cafe 初始化一个新的字符串,然后添加一个 `COMBINING ACTUE ACCENT`(`U+0301`)作为字符串的结尾。最终这个字符串的字符数量仍然是4因为第四个字符是 é ,而不是 e 例如,如果你用四个字符的单词 cafe 初始化一个新的字符串,然后添加一个 `COMBINING ACTUE ACCENT`(`U+0301`)作为字符串的结尾。最终这个字符串的字符数量仍然是4因为第四个字符是 é ,而不是 e
```swift ```swift
var word = "cafe" var word = "cafe"
@ -287,9 +291,9 @@ word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301
print("the number of characters in \(word) is \(word.characters.count)") print("the number of characters in \(word) is \(word.characters.count)")
// 打印输出 "the number of characters in café is 4" // 打印输出 "the number of characters in café is 4"
``` ```
> 注意: > 注意:
> 可扩展的字符群集可以组成一个或者多个 Unicode 标量。这意味着不同的字符以及相同字符的不同表示方式可能需要不同数量的内存空间来存储。所以 Swift 中的字符在一个字符串中并不一定占用相同的内存空间数量。因此在没有获取字符串的可扩展的字符群的范围时候,就不能计算出字符串的字符数量。如果您正在处理一个长字符串,需要注意`characters`属性必须遍历全部的 Unicode 标量,来确定字符串的字符数量。 > 可扩展的字符群集可以组成一个或者多个 Unicode 标量。这意味着不同的字符以及相同字符的不同表示方式可能需要不同数量的内存空间来存储。所以 Swift 中的字符在一个字符串中并不一定占用相同的内存空间数量。因此在没有获取字符串的可扩展的字符群的范围时候,就不能计算出字符串的字符数量。如果您正在处理一个长字符串,需要注意`characters`属性必须遍历全部的 Unicode 标量,来确定字符串的字符数量。
> 另外需要注意的是通过`characters`返回的字符数量并不总是与包含相同字符的`NSString`的`length`属性相同。`NSString`的`length`属性是利用 UTF-16 表示的十六位代码单元数字,而不是 Unicode 可扩展的字符群集。 > 另外需要注意的是通过`characters`返回的字符数量并不总是与包含相同字符的`NSString`的`length`属性相同。`NSString`的`length`属性是利用 UTF-16 表示的十六位代码单元数字,而不是 Unicode 可扩展的字符群集。
@ -361,24 +365,24 @@ let range = advance(welcome.endIndex, -6)..<welcome.endIndex
welcome.removeRange(range) welcome.removeRange(range)
// welcome 现在等于 "hello" // welcome 现在等于 "hello"
``` ```
<a name="comparing_strings"></a> <a name="comparing_strings"></a>
## 比较字符串 (Comparing Strings) ## 比较字符串 (Comparing Strings)
Swift 提供了三种方式来比较文本值:字符串字符相等、前缀相等和后缀相等。 Swift 提供了三种方式来比较文本值:字符串字符相等、前缀相等和后缀相等。
<a name="string_and_character_equality"></a> <a name="string_and_character_equality"></a>
### 字符串/字符相等 (String and Character Equality) ### 字符串/字符相等 (String and Character Equality)
字符串/字符可以用等于操作符(`==`)和不等于操作符(`!=`),详细描述在 [Comparison Operators](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID70) 字符串/字符可以用等于操作符(`==`)和不等于操作符(`!=`),详细描述在[比较运算符](./02_Basic_Operators.html#comparison_operators)
```swift ```swift
let quotation = "We're a lot alike, you and I." let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I." let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation { if quotation == sameQuotation {
print("These two strings are considered equal") print("These two strings are considered equal")
} }
// 打印输出 "These two strings are considered equal" // 打印输出 "These two strings are considered equal"
``` ```
如果两个字符串(或者两个字符)的可扩展的字形群集是标准相等的,那就认为它们是相等的。在这个情况下,即使可扩展的字形群集是有不同的 Unicode 标量构成的,只要它们有同样的语言意义和外观,就认为它们标准相等。 如果两个字符串(或者两个字符)的可扩展的字形群集是标准相等的,那就认为它们是相等的。在这个情况下,即使可扩展的字形群集是有不同的 Unicode 标量构成的,只要它们有同样的语言意义和外观,就认为它们标准相等。
@ -404,18 +408,18 @@ if latinCapitalLetterA != cyrillicCapitalLetterA {
print("These two characters are not equivalent") print("These two characters are not equivalent")
} }
// 打印 "These two characters are not equivalent" // 打印 "These two characters are not equivalent"
``` ```
> 注意: > 注意:
> 在 Swift 中,字符串和字符并不区分区域。 > 在 Swift 中,字符串和字符并不区分区域。
<a name="prefix_and_suffix_equality"></a> <a name="prefix_and_suffix_equality"></a>
### 前缀/后缀相等 (Prefix and Suffix Equality) ### 前缀/后缀相等 (Prefix and Suffix Equality)
通过调用字符串的`hasPrefix(_:)`/`hasSuffix(_:)`方法来检查字符串是否拥有特定前缀/后缀,两个方法均需要以字符串作为参数传入并传出`Boolean`值。 通过调用字符串的`hasPrefix(_:)`/`hasSuffix(_:)`方法来检查字符串是否拥有特定前缀/后缀,两个方法均需要以字符串作为参数传入并传出`Boolean`值。
下面的例子以一个字符串数组表示莎士比亚话剧《罗密欧与朱丽叶》中前两场的场景位置: 下面的例子以一个字符串数组表示莎士比亚话剧《罗密欧与朱丽叶》中前两场的场景位置:
```swift ```swift
let romeoAndJuliet = [ let romeoAndJuliet = [
"Act 1 Scene 1: Verona, A public place", "Act 1 Scene 1: Verona, A public place",
@ -429,11 +433,11 @@ let romeoAndJuliet = [
"Act 2 Scene 4: A street in Verona", "Act 2 Scene 4: A street in Verona",
"Act 2 Scene 5: Capulet's mansion", "Act 2 Scene 5: Capulet's mansion",
"Act 2 Scene 6: Friar Lawrence's cell" "Act 2 Scene 6: Friar Lawrence's cell"
] ]
``` ```
您可以调用`hasPrefix(_:)`方法来计算话剧中第一幕的场景数: 您可以调用`hasPrefix(_:)`方法来计算话剧中第一幕的场景数:
```swift ```swift
var act1SceneCount = 0 var act1SceneCount = 0
for scene in romeoAndJuliet { for scene in romeoAndJuliet {
@ -442,11 +446,11 @@ for scene in romeoAndJuliet {
} }
} }
print("There are \(act1SceneCount) scenes in Act 1") print("There are \(act1SceneCount) scenes in Act 1")
// 打印输出 "There are 5 scenes in Act 1" // 打印输出 "There are 5 scenes in Act 1"
``` ```
相似地,您可以用`hasSuffix(_:)`方法来计算发生在不同地方的场景数: 相似地,您可以用`hasSuffix(_:)`方法来计算发生在不同地方的场景数:
```swift ```swift
var mansionCount = 0 var mansionCount = 0
var cellCount = 0 var cellCount = 0
@ -458,37 +462,37 @@ for scene in romeoAndJuliet {
} }
} }
print("\(mansionCount) mansion scenes; \(cellCount) cell scenes") print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
// 打印输出 "6 mansion scenes; 2 cell scenes" // 打印输出 "6 mansion scenes; 2 cell scenes"
``` ```
> 注意: > 注意:
> `hasPrefix(_:)`和`hasSuffix(_:)`方法都是在每个字符串中一个一个字符的比较其可扩展的字符群集是否标准相等,详细描述在[字符串/字符相等](#string_and_character_equality)。 > `hasPrefix(_:)`和`hasSuffix(_:)`方法都是在每个字符串中一个一个字符的比较其可扩展的字符群集是否标准相等,详细描述在[字符串/字符相等](#string_and_character_equality)。
<a name="unicode_representations_of_strings"></a> <a name="unicode_representations_of_strings"></a>
## 字符串的 Unicode 表示形式Unicode Representations of Strings ## 字符串的 Unicode 表示形式Unicode Representations of Strings
当一个 Unicode 字符串被写进文本文件或者其他储存时,字符串中的 Unicode 标量会用 Unicode 定义的几种编码格式编码。每一个字符串中的小块编码都被称为代码单元。这些包括 UTF-8 编码格式编码字符串为8位的代码单元 UTF-16 编码格式编码字符串位16位的代码单元以及 UTF-32 编码格式编码字符串32位的代码单元 当一个 Unicode 字符串被写进文本文件或者其他储存时,字符串中的 Unicode 标量会用 Unicode 定义的几种编码格式编码。每一个字符串中的小块编码都被称为代码单元。这些包括 UTF-8 编码格式编码字符串为8位的代码单元 UTF-16 编码格式编码字符串位16位的代码单元以及 UTF-32 编码格式编码字符串32位的代码单元
Swift 提供了几种不同的方式来访问字符串的 Unicode 表示形式。 Swift 提供了几种不同的方式来访问字符串的 Unicode 表示形式。
您可以利用`for-in`来对字符串进行遍历,从而以 Unicode 可扩展的字符群集的方式访问每一个字符值。 您可以利用`for-in`来对字符串进行遍历,从而以 Unicode 可扩展的字符群集的方式访问每一个字符值。
该过程在 [使用字符](#working_with_characters) 中进行了描述。 该过程在 [使用字符](#working_with_characters) 中进行了描述。
另外,能够以其他三种 Unicode 兼容的方式访问字符串的值: 另外,能够以其他三种 Unicode 兼容的方式访问字符串的值:
* UTF-8 代码单元集合 (利用字符串的`utf8`属性进行访问) * UTF-8 代码单元集合 (利用字符串的`utf8`属性进行访问)
* UTF-16 代码单元集合 (利用字符串的`utf16`属性进行访问) * UTF-16 代码单元集合 (利用字符串的`utf16`属性进行访问)
* 21位的 Unicode 标量值集合,也就是字符串的 UTF-32 编码格式 (利用字符串的`unicodeScalars`属性进行访问) * 21位的 Unicode 标量值集合,也就是字符串的 UTF-32 编码格式 (利用字符串的`unicodeScalars`属性进行访问)
下面由`D``o``g``‼`(`DOUBLE EXCLAMATION MARK`, Unicode 标量 `U+203C`)和`🐶`(`DOG FACE`Unicode 标量为`U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示: 下面由`D``o``g``‼`(`DOUBLE EXCLAMATION MARK`, Unicode 标量 `U+203C`)和`🐶`(`DOG FACE`Unicode 标量为`U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示:
```swift ```swift
let dogString = "Dog‼🐶" let dogString = "Dog‼🐶"
``` ```
<a name="UTF-8_representation"></a> <a name="UTF-8_representation"></a>
### UTF-8 表示 ### UTF-8 表示
您可以通过遍历字符串的`utf8`属性来访问它的`UTF-8`表示。 您可以通过遍历字符串的`utf8`属性来访问它的`UTF-8`表示。
其为`String.UTF8View`类型的属性,`UTF8View`是无符号8位 (`UInt8`) 值的集合,每一个`UInt8`值都是一个字符的 UTF-8 表示: 其为`String.UTF8View`类型的属性,`UTF8View`是无符号8位 (`UInt8`) 值的集合,每一个`UInt8`值都是一个字符的 UTF-8 表示:
<body> <body>
@ -530,25 +534,25 @@ let dogString = "Dog‼🐶"
</tr> </tr>
</table> </table>
</center> </center>
</body> </body>
```swift ```swift
for codeUnit in dogString.utf8 { for codeUnit in dogString.utf8 {
print("\(codeUnit) ", appendNewline: false) print("\(codeUnit) ", appendNewline: false)
} }
print("") print("")
// 68 111 103 226 128 188 240 159 144 182 // 68 111 103 226 128 188 240 159 144 182
``` ```
上面的例子中前三个10进制代码单元值 (68, 111, 103) 代表了字符`D``o``g`,它们的 UTF-8 表示与 ASCII 表示相同。 上面的例子中前三个10进制代码单元值 (68, 111, 103) 代表了字符`D``o``g`,它们的 UTF-8 表示与 ASCII 表示相同。
接下来的三个10进制代码单元值 (226, 128, 188) 是`DOUBLE EXCLAMATION MARK`的3字节 UTF-8 表示。 接下来的三个10进制代码单元值 (226, 128, 188) 是`DOUBLE EXCLAMATION MARK`的3字节 UTF-8 表示。
最后的四个代码单元值 (240, 159, 144, 182) 是`DOG FACE`的4字节 UTF-8 表示。 最后的四个代码单元值 (240, 159, 144, 182) 是`DOG FACE`的4字节 UTF-8 表示。
<a name="UTF-16_representation"></a> <a name="UTF-16_representation"></a>
### UTF-16 表示 ### UTF-16 表示
您可以通过遍历字符串的`utf16`属性来访问它的`UTF-16`表示。 您可以通过遍历字符串的`utf16`属性来访问它的`UTF-16`表示。
其为`String.UTF16View`类型的属性,`UTF16View`是无符号16位 (`UInt16`) 值的集合,每一个`UInt16`都是一个字符的 UTF-16 表示: 其为`String.UTF16View`类型的属性,`UTF16View`是无符号16位 (`UInt16`) 值的集合,每一个`UInt16`都是一个字符的 UTF-16 表示:
<body> <body>
<center> <center>
@ -582,28 +586,28 @@ print("")
</table> </table>
</center> </center>
</body> </body>
```swift ```swift
for codeUnit in dogString.utf16 { for codeUnit in dogString.utf16 {
print("\(codeUnit) ", appendNewline: false) print("\(codeUnit) ", appendNewline: false)
} }
print("") print("")
// 68 111 103 8252 55357 56374 // 68 111 103 8252 55357 56374
``` ```
同样,前三个代码单元值 (68, 111, 103) 代表了字符`D``o``g`,它们的 UTF-16 代码单元和 UTF-8 完全相同(因为这些 Unicode 标量表示 ASCII 字符)。 同样,前三个代码单元值 (68, 111, 103) 代表了字符`D``o``g`,它们的 UTF-16 代码单元和 UTF-8 完全相同(因为这些 Unicode 标量表示 ASCII 字符)。
第四个代码单元值 (8252) 是一个等于十六进制203C的的十进制值。这个代表了`DOUBLE EXCLAMATION MARK`字符的 Unicode 标量值`U+203C`。这个字符在 UTF-16 中可以用一个代码单元表示。 第四个代码单元值 (8252) 是一个等于十六进制203C的的十进制值。这个代表了`DOUBLE EXCLAMATION MARK`字符的 Unicode 标量值`U+203C`。这个字符在 UTF-16 中可以用一个代码单元表示。
第五和第六个代码单元值 (55357 和 56374) 是`DOG FACE`字符的UTF-16 表示。 第五和第六个代码单元值 (55357 和 56374) 是`DOG FACE`字符的UTF-16 表示。
第一个值为`U+D83D`(十进制值为 55357),第二个值为`U+DC36`(十进制值为 56374)。 第一个值为`U+D83D`(十进制值为 55357),第二个值为`U+DC36`(十进制值为 56374)。
<a name="unicode_scalars_representation"></a> <a name="unicode_scalars_representation"></a>
### Unicode 标量表示 (Unicode Scalars Representation) ### Unicode 标量表示 (Unicode Scalars Representation)
您可以通过遍历字符串的`unicodeScalars`属性来访问它的 Unicode 标量表示。 您可以通过遍历字符串的`unicodeScalars`属性来访问它的 Unicode 标量表示。
其为`UnicodeScalarView`类型的属性, `UnicodeScalarView``UnicodeScalar`的集合。 其为`UnicodeScalarView`类型的属性, `UnicodeScalarView``UnicodeScalar`的集合。
`UnicodeScalar`是21位的 Unicode 代码点。 `UnicodeScalar`是21位的 Unicode 代码点。
每一个`UnicodeScalar`拥有一个值属性可以返回对应的21位数值`UInt32`来表示: 每一个`UnicodeScalar`拥有一个值属性可以返回对应的21位数值`UInt32`来表示:
<body> <body>
@ -636,22 +640,22 @@ print("")
</table> </table>
</center> </center>
</body> </body>
```swift ```swift
for scalar in dogString.unicodeScalars { for scalar in dogString.unicodeScalars {
print("\(scalar.value) ", appendNewline: false) print("\(scalar.value) ", appendNewline: false)
} }
print("") print("")
// 68 111 103 8252 128054 // 68 111 103 8252 128054
``` ```
前三个代码单元值 (68, 111, 103) 仍然代表字符`D``o``g` 前三个代码单元值 (68, 111, 103) 仍然代表字符`D``o``g`
第四个代码单元值 (8252) 仍然是一个等于十六进制203C的的十进制值。这个代表了`DOUBLE EXCLAMATION MARK`字符的 Unicode 标量`U+203C` 第四个代码单元值 (8252) 仍然是一个等于十六进制203C的的十进制值。这个代表了`DOUBLE EXCLAMATION MARK`字符的 Unicode 标量`U+203C`
第五位数值128054是一个十六进制1F436的十进制表示。其等同于`DOG FACE`的Unicode 标量`U+1F436` 第五位数值128054是一个十六进制1F436的十进制表示。其等同于`DOG FACE`的Unicode 标量`U+1F436`
作为查询字符值属性的一种替代方法,每个`UnicodeScalar`值也可以用来构建一个新的字符串值,比如在字符串插值中使用: 作为查询字符值属性的一种替代方法,每个`UnicodeScalar`值也可以用来构建一个新的字符串值,比如在字符串插值中使用:
```swift ```swift
for scalar in dogString.unicodeScalars { for scalar in dogString.unicodeScalars {
print("\(scalar) ") print("\(scalar) ")
@ -660,5 +664,5 @@ for scalar in dogString.unicodeScalars {
// o // o
// g // g
// ‼ // ‼
// 🐶 // 🐶
``` ```

View File

@ -1,5 +1,9 @@
> 翻译:[zqp](https://github.com/zqp), [JackAlan](https://github.com/AlanMelody) > 1.0
> 校对:[shinyzhu](https://github.com/shinyzhu), [stanzhai](https://github.com/stanzhai), [feiin](https://github.com/feiin), [JackAlan](https://github.com/AlanMelody) > 翻译:[zqp](https://github.com/zqp),
> 校对:[shinyzhu](https://github.com/shinyzhu), [stanzhai](https://github.com/stanzhai), [feiin](https://github.com/feiin)
> 2.0
> 翻译+校对:[JackAlan](https://github.com/AlanMelody)
# 集合类型 (Collection Types) # 集合类型 (Collection Types)
----------------- -----------------
@ -18,7 +22,7 @@ Swift 语言提供`Arrays`、`Sets`和`Dictionaries`三种基本的集合类型
Swift 语言中的`Arrays``Sets``Dictionaries`中存储的数据值类型必须明确。这意味着我们不能把不正确的数据类型插入其中。同时这也说明我们完全可以对取回值的类型非常自信。 Swift 语言中的`Arrays``Sets``Dictionaries`中存储的数据值类型必须明确。这意味着我们不能把不正确的数据类型插入其中。同时这也说明我们完全可以对取回值的类型非常自信。
> 注意: > 注意:
Swift 的`Arrays``Sets``Dictionaries`类型被实现为泛型集合。更多关于泛型类型和集合,参见 [泛型](23_Generics.html)章节。 Swift 的`Arrays``Sets``Dictionaries`类型被实现为泛型集合。更多关于泛型类型和集合,参见 [泛型](./23_Generics.html)章节。
<a name="mutability_of_collections"></a> <a name="mutability_of_collections"></a>
## 集合的可变性 ## 集合的可变性
@ -35,7 +39,7 @@ Swift 的`Arrays`、`Sets`和`Dictionaries`类型被实现为泛型集合。更
> 注意: > 注意:
Swift 的`Array`类型被桥接到`Foundation`中的`NSArray`类。 Swift 的`Array`类型被桥接到`Foundation`中的`NSArray`类。
更多关于在`Foundation``Cocoa`中使用`Array`的信息,参见 *Using Swift with Cocoa and Obejective-C* 一书。 更多关于在`Foundation``Cocoa`中使用`Array`的信息,参见 [*Using Swift with Cocoa and Obejective-C*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216) 一书。
<a name="array_type_shorthand_syntax"></a> <a name="array_type_shorthand_syntax"></a>
### 数组的简单语法 ### 数组的简单语法
@ -255,14 +259,14 @@ for (index, value) in shoppingList.enumerate() {
> 注意: > 注意:
> Swift的`Set`类型被桥接到`Fundation`中的`NSSet`类。 > Swift的`Set`类型被桥接到`Fundation`中的`NSSet`类。
> 关于使用`Fundation`和`Cocoa`中`Set`的知识,请看 *Using Swift with Cocoa and Objective-C*。 > 关于使用`Fundation`和`Cocoa`中`Set`的知识,请看 [*Using Swift with Cocoa and Objective-C*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)
<a name="hash_values_for_set_types"></a> <a name="hash_values_for_set_types"></a>
#### Set类型的哈希值 #### Set类型的哈希值
为了存储在集合中,该类型必须是可哈希化的-也就是说,该类型必须提供一个方法来计算它的哈希值。一个哈希值是```Int```类型的,它和其他的对象相同,其被用来比较相等与否,比如```a==b```,它遵循的是```a.hashValue == b.hashValue```。 为了存储在集合中,该类型必须是可哈希化的-也就是说,该类型必须提供一个方法来计算它的哈希值。一个哈希值是```Int```类型的,它和其他的对象相同,其被用来比较相等与否,比如```a==b```,它遵循的是```a.hashValue == b.hashValue```。
Swift 的所有基本类型(比如```String```,```Int```,```Double```和```Bool```)默认都是可哈希化的,它可以作为集合的值或者字典的键值类型。没有关联值的枚举成员值(在[枚举部分](08_Enumerations.html)有讲述)默认也是可哈希化的。 Swift 的所有基本类型(比如```String```,```Int```,```Double```和```Bool```)默认都是可哈希化的,它可以作为集合的值或者字典的键值类型。没有关联值的枚举成员值(在[枚举](./08_Enumerations.html)有讲述)默认也是可哈希化的。
> 注意: > 注意:
> 你可以使用你自定义的类型作为集合的值或者是字典的键值类型但你需要使你的自定义类型服从Swift标准库中的`Hashable`协议。服从`Hashable`协议的类型需要提供一个类型为`Int`的取值访问器属性`hashValue`。这个由类型的`hashValue`返回的值不需要在同一程序的不同执行周期或者不同程序之间保持相同。 > 你可以使用你自定义的类型作为集合的值或者是字典的键值类型但你需要使你的自定义类型服从Swift标准库中的`Hashable`协议。服从`Hashable`协议的类型需要提供一个类型为`Int`的取值访问器属性`hashValue`。这个由类型的`hashValue`返回的值不需要在同一程序的不同执行周期或者不同程序之间保持相同。
@ -272,7 +276,7 @@ Swift 的所有基本类型(比如```String```,```Int```,```Double```和```Bool`
* ```a==b```意味着```b==a```(对称性) * ```a==b```意味着```b==a```(对称性)
* ```a==b&&b==c```意味着```a==c```(传递性) * ```a==b&&b==c```意味着```a==c```(传递性)
关于协议遵循的更多信息,请看[协议](22_Protocols.html) 关于协议遵循的更多信息,请看[协议](./22_Protocols.html)
<a name="set_type_syntax"></a> <a name="set_type_syntax"></a>
### Set类型语法 ### Set类型语法
@ -393,7 +397,7 @@ for genre in favoriteGenres {
// Hip hop // Hip hop
``` ```
更多关于`for-in`循环信息,参见[For循环](05_Control_Flow.html#for_loops)。 更多关于`for-in`循环信息,参见[For循环](./05_Control_Flow.html#for_loops)。
Swift 的`Set`类型没有确定的顺序,为了按照特定顺序来遍历一个`Set`中值可以使用`sort()`方法,它将根据提供的序列返回一个排序的集合. Swift 的`Set`类型没有确定的顺序,为了按照特定顺序来遍历一个`Set`中值可以使用`sort()`方法,它将根据提供的序列返回一个排序的集合.
@ -471,7 +475,7 @@ farmAnimals.isDisjointWith(cityAnimals)
> 注意: > 注意:
> Swiftly 的`Dictionary` 类型被桥接到Foundation的`NSDictionary`类。 > Swiftly 的`Dictionary` 类型被桥接到Foundation的`NSDictionary`类。
> 更多关于在`Foundation`和`Cocoa`中使用`Dictionary`类型的信息,参见 *Using Swift with Cocoa and Obejective-C* 一书。 > 更多关于在`Foundation`和`Cocoa`中使用`Dictionary`类型的信息,参见 [*Using Swift with Cocoa and Obejective-C*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216) 一书。
<a name="dictionary_type_shorthand_syntax"></a> <a name="dictionary_type_shorthand_syntax"></a>
## 字典类型快捷语法 ## 字典类型快捷语法
@ -640,7 +644,7 @@ for (airportCode, airportName) in airports {
// LHR: London Heathrow // LHR: London Heathrow
``` ```
更多关于`for-in`循环的信息,参见[For 循环](05_Control_Flow.html#for_loops)。 更多关于`for-in`循环的信息,参见[For 循环](./05_Control_Flow.html#for_loops)。
通过访问`keys`或者`values`属性,我们也可以遍历字典的键或者值。 通过访问`keys`或者`values`属性,我们也可以遍历字典的键或者值。

View File

@ -1,5 +1,9 @@
> 翻译:[vclwei](https://github.com/vclwei), [coverxit](https://github.com/coverxit), [NicePiao](https://github.com/NicePiao), [JackAlan](https://github.com/AlanMelody) > 1.0
> 校对:[coverxit](https://github.com/coverxit), [stanzhai](https://github.com/stanzhai), [JackAlan](https://github.com/AlanMelody) > 翻译:[vclwei](https://github.com/vclwei), [coverxit](https://github.com/coverxit), [NicePiao](https://github.com/NicePiao)
> 校对:[coverxit](https://github.com/coverxit), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[JackAlan](https://github.com/AlanMelody)
# 控制流 # 控制流
----------------- -----------------
@ -87,7 +91,7 @@ for (animalName, legCount) in numberOfLegs {
// spiders have 8 legs // spiders have 8 legs
``` ```
字典元素的遍历顺序和插入顺序可能不同,字典的内容在内部是无序的,所以遍历元素时不能保证顺序。关于数组和字典,详情参见[集合类型](04_Collection_Types.html)。 字典元素的遍历顺序和插入顺序可能不同,字典的内容在内部是无序的,所以遍历元素时不能保证顺序。关于数组和字典,详情参见[集合类型](./04_Collection_Types.html)。
<a name="for"></a> <a name="for"></a>
@ -529,8 +533,9 @@ case let (x, y):
- `break` - `break`
- `fallthrough` - `fallthrough`
- `return` - `return`
- `throw`
我们将会在下面讨论`continue`、`break`和`fallthrough`语句。`return`语句将会在[函数](06_Functions.html)章节讨论 我们将会在下面讨论`continue`、`break`和`fallthrough`语句。`return`语句将会在[函数](./06_Functions.html)章节讨论`throw`语句会在[错误抛出](./18_Error_Handling.html#throwing_errors)
<a name="continue"></a> <a name="continue"></a>
### Continue ### Continue

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[honghaoz](https://github.com/honghaoz) > 翻译:[honghaoz](https://github.com/honghaoz)
> 校对:[LunaticM](https://github.com/LunaticM) > 校对:[LunaticM](https://github.com/LunaticM)
> 2.0
> 翻译+校对:[dreamkidd](https://github.com/dreamkidd)
# 函数Functions # 函数Functions
----------------- -----------------
@ -116,6 +120,7 @@ print(sayHello("Tim", alreadyGreeted: true))
当调用超过一个参数的函数时,第一个参数后的参数根据其对应的参数名称标记,函数参数命名在[函数参数名称Function Parameter Names](#Function_Parameter_Names)有更详细的描述. 当调用超过一个参数的函数时,第一个参数后的参数根据其对应的参数名称标记,函数参数命名在[函数参数名称Function Parameter Names](#Function_Parameter_Names)有更详细的描述.
<a name="functions_without_return_values"></a>
### 无返回值函数Functions Without Return Values ### 无返回值函数Functions Without Return Values
函数可以没有返回值。下面是 `sayHello(_:)` 函数的另一个版本,叫 `sayGoodbye(_:)`,这个函数直接输出 `String` 值,而不是返回它: 函数可以没有返回值。下面是 `sayHello(_:)` 函数的另一个版本,叫 `sayGoodbye(_:)`,这个函数直接输出 `String` 值,而不是返回它:
@ -242,6 +247,7 @@ someFunction(1, secondParameterName: 2)
一般情况下,第一个参数省略其外部参数名,第二个以后的参数使用其本地参数名作为自己的外部参数名.所有参数需要有不同的本地参数名,但可以共享相同的外部参数名. 一般情况下,第一个参数省略其外部参数名,第二个以后的参数使用其本地参数名作为自己的外部参数名.所有参数需要有不同的本地参数名,但可以共享相同的外部参数名.
<a name="specifying_external_parameter_names"></a>
### 指定外部参数名(Specifying External Parameter Names) ### 指定外部参数名(Specifying External Parameter Names)
你可以在本地参数名前指定外部参数名,中间以逗号分隔. 你可以在本地参数名前指定外部参数名,中间以逗号分隔.
@ -373,6 +379,7 @@ let paddedString = alignRight(originalString, totalLength: 10, pad: "-")
> 注意: > 注意:
> 对变量参数所进行的修改在函数调用结束后便消失了,并且对于函数体外是不可见的。变量参数仅仅存在于函数调用的生命周期中。 > 对变量参数所进行的修改在函数调用结束后便消失了,并且对于函数体外是不可见的。变量参数仅仅存在于函数调用的生命周期中。
<a name="in_out_parameters"></a>
### 输入输出参数In-Out Parameters ### 输入输出参数In-Out Parameters
变量参数正如上面所述仅仅能在函数体内被更改。如果你想要一个函数可以修改参数的值并且想要在这些修改在函数调用结束后仍然存在那么就应该把这个参数定义为输入输出参数In-Out Parameters 变量参数正如上面所述仅仅能在函数体内被更改。如果你想要一个函数可以修改参数的值并且想要在这些修改在函数调用结束后仍然存在那么就应该把这个参数定义为输入输出参数In-Out Parameters

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[wh1100717](https://github.com/wh1100717) > 翻译:[wh1100717](https://github.com/wh1100717)
> 校对:[lyuka](https://github.com/lyuka) > 校对:[lyuka](https://github.com/lyuka)
> 2.0
> 翻译+校对:[100mango](https://github.com/100mango)
# 闭包Closures # 闭包Closures
----------------- -----------------
@ -20,7 +24,7 @@ Swift 中的闭包与 C 和 Objective-C 中的代码块blocks以及其他
> 注意: > 注意:
> 如果您不熟悉捕获capturing这个概念也不用担心您可以在 [值捕获](#capturing_values) 章节对其进行详细了解。 > 如果您不熟悉捕获capturing这个概念也不用担心您可以在 [值捕获](#capturing_values) 章节对其进行详细了解。
在[函数](../chapter2/06_Functions.html) 章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三种形式之一: 在[函数](./06_Functions.html) 章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三种形式之一:
* 全局函数是一个有名字但不会捕获任何值的闭包 * 全局函数是一个有名字但不会捕获任何值的闭包
* 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包 * 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
@ -37,7 +41,7 @@ Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进
## 闭包表达式Closure Expressions ## 闭包表达式Closure Expressions
[嵌套函数](../chapter2/06_Functions.html#nested_function) 是一个在较复杂函数中方便进行命名和定义自包含代码模块的方式。当然,有时候撰写小巧的没有完整定义和命名的类函数结构也是很有用处的,尤其是在您处理一些函数并需要将另外一些函数作为该函数的参数时。 [嵌套函数](./06_Functions.html#nested_function) 是一个在较复杂函数中方便进行命名和定义自包含代码模块的方式。当然,有时候撰写小巧的没有完整定义和命名的类函数结构也是很有用处的,尤其是在您处理一些函数并需要将另外一些函数作为该函数的参数时。
闭包表达式是一种利用简洁语法构建内联闭包的方式。 闭包表达式是一种利用简洁语法构建内联闭包的方式。
闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。 闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。
@ -172,7 +176,7 @@ Swift 的`String`类型定义了关于大于号 (`>`) 的字符串实现,其
reversed = names.sort(>) reversed = names.sort(>)
``` ```
更多关于运算符表达式的内容请查看 [运算符函数](../chapter2/24_Advanced_Operators.html#operator_functions)。 更多关于运算符表达式的内容请查看 [运算符函数](./24_Advanced_Operators.html#operator_functions)。
<a name="trailing_closures"></a> <a name="trailing_closures"></a>
## 尾随闭包Trailing Closures ## 尾随闭包Trailing Closures
@ -246,7 +250,7 @@ let strings = numbers.map {
`map`在数组中为每一个元素调用了闭包表达式。 `map`在数组中为每一个元素调用了闭包表达式。
您不需要指定闭包的输入参数`number`的类型,因为可以通过要映射的数组类型进行推断。 您不需要指定闭包的输入参数`number`的类型,因为可以通过要映射的数组类型进行推断。
闭包`number`参数被声明为一个变量参数(变量的具体描述请参看[常量参数和变量参数](../chapter2/06_Functions.html#constant_and_variable_parameters)),因此可以在闭包函数体内对其进行修改。闭包表达式制定了返回类型为`String`,以表明存储映射值的新数组类型为`String` 闭包`number`参数被声明为一个变量参数(变量的具体描述请参看[常量参数和变量参数](./06_Functions.html#constant_and_variable_parameters)),因此可以在闭包函数体内对其进行修改。闭包表达式制定了返回类型为`String`,以表明存储映射值的新数组类型为`String`
闭包表达式在每次被调用的时候创建了一个字符串并返回。 闭包表达式在每次被调用的时候创建了一个字符串并返回。
其使用求余运算符 (number % 10) 计算最后一位数字并利用`digitNames`字典获取所映射的字符串。 其使用求余运算符 (number % 10) 计算最后一位数字并利用`digitNames`字典获取所映射的字符串。
@ -296,7 +300,7 @@ func makeIncrementor(forIncrement amount: Int) -> () -> Int {
`makeIncrementor`返回类型为`() -> Int` `makeIncrementor`返回类型为`() -> Int`
这意味着其返回的是一个函数,而不是一个简单类型值。 这意味着其返回的是一个函数,而不是一个简单类型值。
该函数在每次调用时不接受参数只返回一个`Int`类型的值。 该函数在每次调用时不接受参数只返回一个`Int`类型的值。
关于函数返回其他函数的内容,请查看[函数类型作为返回类型](../chapter2/06_Functions.html#function_types_as_return_types)。 关于函数返回其他函数的内容,请查看[函数类型作为返回类型](./06_Functions.html#function_types_as_return_types)。
`makeIncrementor`函数定义了一个整型变量`runningTotal`(初始为0) 用来存储当前跑步总数。 `makeIncrementor`函数定义了一个整型变量`runningTotal`(初始为0) 用来存储当前跑步总数。
该值通过`incrementor`返回。 该值通过`incrementor`返回。
@ -352,7 +356,7 @@ incrementByTen()
> 注意: > 注意:
> 如果您将闭包赋值给一个类实例的属性,并且该闭包通过指向该实例或其成员来捕获了该实例,您将创建一个在闭包和实例间的强引用环。 > 如果您将闭包赋值给一个类实例的属性,并且该闭包通过指向该实例或其成员来捕获了该实例,您将创建一个在闭包和实例间的强引用环。
> Swift 使用捕获列表来打破这种强引用环。更多信息,请参考 [闭包引起的循环强引用](../chapter2/16_Automatic_Reference_Counting.html#strong_reference_cycles_for_closures)。 > Swift 使用捕获列表来打破这种强引用环。更多信息,请参考 [闭包引起的循环强引用](./16_Automatic_Reference_Counting.html#strong_reference_cycles_for_closures)。
<a name="closures_are_reference_types"></a> <a name="closures_are_reference_types"></a>
## 闭包是引用类型Closures Are Reference Types ## 闭包是引用类型Closures Are Reference Types

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[yankuangshi](https://github.com/yankuangshi) > 翻译:[yankuangshi](https://github.com/yankuangshi)
> 校对:[shinyzhu](https://github.com/shinyzhu) > 校对:[shinyzhu](https://github.com/shinyzhu)
> 2.0
> 翻译+校对:[futantan](https://github.com/futantan)
# 枚举Enumerations # 枚举Enumerations
--- ---
@ -20,7 +24,7 @@
在 Swift 中枚举类型是一等公民first-class。它们采用了很多传统上只被类class所支持的特征例如计算型属性computed properties用于提供关于枚举当前值的附加信息 实例方法instance methods用于提供和枚举所代表的值相关联的功能。枚举也可以定义构造函数initializers来提供一个初始值可以在原始的实现基础上扩展它们的功能可以遵守协议protocols来提供标准的功能。 在 Swift 中枚举类型是一等公民first-class。它们采用了很多传统上只被类class所支持的特征例如计算型属性computed properties用于提供关于枚举当前值的附加信息 实例方法instance methods用于提供和枚举所代表的值相关联的功能。枚举也可以定义构造函数initializers来提供一个初始值可以在原始的实现基础上扩展它们的功能可以遵守协议protocols来提供标准的功能。
欲了解更多相关信息,请参见[属性Properties](10_Properties.html)[方法Methods](11_Methods.html)[构造过程Initialization](14_Initialization.html)[扩展Extensions](20_Extensions.html)和[协议Protocols](21_Protocols.html)。 欲了解更多相关信息,请参见[属性Properties](./10_Properties.html)[方法Methods](./11_Methods.html)[构造过程Initialization](./14_Initialization.html)[扩展Extensions](./20_Extensions.html)和[协议Protocols](./21_Protocols.html)。
<a name="enumeration_syntax"></a> <a name="enumeration_syntax"></a>
## 枚举语法 ## 枚举语法
@ -97,7 +101,7 @@ case .West:
等等以此类推。 等等以此类推。
正如在[控制流Control Flow](05_Control_Flow.html)中介绍的那样,在判断一个枚举类型的值时,`switch`语句必须穷举所有情况。如果忽略了`.West`这种情况,上面那段代码将无法通过编译,因为它没有考虑到`CompassPoint`的全部成员。强制性全部穷举的要求确保了枚举成员不会被意外遗漏。 正如在[控制流Control Flow](./05_Control_Flow.html)中介绍的那样,在判断一个枚举类型的值时,`switch`语句必须穷举所有情况。如果忽略了`.West`这种情况,上面那段代码将无法通过编译,因为它没有考虑到`CompassPoint`的全部成员。强制性全部穷举的要求确保了枚举成员不会被意外遗漏。
当不需要匹配每个枚举成员的时候,你可以提供一个默认`default`分支来涵盖所有未明确被提出的枚举成员: 当不需要匹配每个枚举成员的时候,你可以提供一个默认`default`分支来涵盖所有未明确被提出的枚举成员:
@ -187,7 +191,7 @@ case let .QRCode(productCode):
<a name="raw_values"></a> <a name="raw_values"></a>
## 原始值Raw Values ## 原始值Raw Values
在[Associated Values](#raw_values)小节的条形码例子中演示了一个枚举的成员如何声明它们存储不同类型的相关值。作为相关值的另一种选择,枚举成员可以被默认值(称为原始值)赋值,其中这些原始值具有相同的类型。 在[相关值](#raw_values)小节的条形码例子中演示了一个枚举的成员如何声明它们存储不同类型的相关值。作为相关值的另一种选择,枚举成员可以被默认值(称为原始值)赋值,其中这些原始值具有相同的类型。
这里是一个枚举成员存储 ASCII 码的例子: 这里是一个枚举成员存储 ASCII 码的例子:
@ -199,7 +203,7 @@ enum ASCIIControlCharacter: Character {
} }
``` ```
在这里,`ASCIIControlCharacter`的枚举类型的原始值类型被定义为字符型`Character`,并被设置了一些比较常见的 ASCII 控制字符。字符值的描述请详见字符串和字符[`Strings and Characters`](03_Strings_and_Characters.html)部分。 在这里,`ASCIIControlCharacter`的枚举类型的原始值类型被定义为字符型`Character`,并被设置了一些比较常见的 ASCII 控制字符。字符值的描述请详见[字符串和字符](./03_Strings_and_Characters.html)部分。
原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。 原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。
@ -261,7 +265,7 @@ let possiblePlanet = Planet(rawValue: 7)
<!-- TODO 连接 --> <!-- TODO 连接 -->
>注意: >注意:
>原始值构造器是一个可失败构造器,因为并不是每一个原始值都有与之对应的枚举成员。更多信息请参见[Failableinitializers](http://) >原始值构造器是一个可失败构造器,因为并不是每一个原始值都有与之对应的枚举成员。更多信息请参见[可失败构造器](../chapter3/05_Declarations#failable_initializers)
如果你试图寻找一个位置为9的行星通过参数为`rawValue`构造函数返回的可选`Planet`值将是`nil` 如果你试图寻找一个位置为9的行星通过参数为`rawValue`构造函数返回的可选`Planet`值将是`nil`

View File

@ -1,5 +1,9 @@
> 翻译:[JaySurplus](https://github.com/JaySurplus),[SkyJean](https://github.com/SkyJean) > 1.0
> 校对:[sg552](https://github.com/sg552),[SkyJean](https://github.com/SkyJean) > 翻译:[JaySurplus](https://github.com/JaySurplus)
> 校对:[sg552](https://github.com/sg552)
> 2.0
> 翻译+校对:[SkyJean](https://github.com/SkyJean)
# 类和结构体 # 类和结构体
@ -31,7 +35,7 @@ Swift 中类和结构体有很多共同点。共同处在于:
* 通过扩展以增加默认实现的功能 * 通过扩展以增加默认实现的功能
* 实现协议以提供某种标准功能 * 实现协议以提供某种标准功能
更多信息请参见 [属性](10_Properties.html)[方法](11_Methods.html)[下标脚本](12_Subscripts.html)[初始过程](14_Initialization.html)[扩展](20_Extensions.html),和[协议](21_Protocols.html)。 更多信息请参见 [属性](./10_Properties.html)[方法](./11_Methods.html)[下标脚本](./12_Subscripts.html)[初始过程](./14_Initialization.html)[扩展](./20_Extensions.html),和[协议](./21_Protocols.html)。
与结构体相比,类还有如下的附加功能: 与结构体相比,类还有如下的附加功能:
@ -40,7 +44,7 @@ Swift 中类和结构体有很多共同点。共同处在于:
* 解构器允许一个类实例释放任何其所被分配的资源 * 解构器允许一个类实例释放任何其所被分配的资源
* 引用计数允许对一个类的多次引用 * 引用计数允许对一个类的多次引用
更多信息请参见[继承](13_Inheritance.html)[类型转换](20_Type_Casting.html)[析构过程](15_Deinitialization),和[自动引用计数](16_Automatic_Reference_Counting)。 更多信息请参见[继承](./13_Inheritance.html)[类型转换](./20_Type_Casting.html)[析构过程](./15_Deinitialization),和[自动引用计数](./16_Automatic_Reference_Counting)。
> 注意: > 注意:
结构体总是通过被复制的方式在代码中传递,因此请不要使用引用计数。 结构体总是通过被复制的方式在代码中传递,因此请不要使用引用计数。
@ -91,7 +95,7 @@ let someResolution = Resolution()
let someVideoMode = VideoMode() let someVideoMode = VideoMode()
``` ```
结构体和类都使用构造器语法来生成新的实例。构造器语法的最简单形式是在结构体或者类的类型名称后跟随一对空括号,如`Resolution()``VideoMode()`。通过这种方式所创建的类或者结构体实例,其属性均会被初始化为默认值。[构造过程](14_Initialization.html)章节会对类和结构体的初始化进行更详细的讨论。 结构体和类都使用构造器语法来生成新的实例。构造器语法的最简单形式是在结构体或者类的类型名称后跟随一对空括号,如`Resolution()``VideoMode()`。通过这种方式所创建的类或者结构体实例,其属性均会被初始化为默认值。[构造过程](./14_Initialization.html)章节会对类和结构体的初始化进行更详细的讨论。
### 属性访问 ### 属性访问
@ -130,7 +134,7 @@ print("The width of someVideoMode is now \(someVideoMode.resolution.width)")
let vga = Resolution(width:640, height: 480) let vga = Resolution(width:640, height: 480)
``` ```
与结构体不同,类实例没有默认的成员逐一构造器。[构造过程](14_Initialization.html)章节会对构造器进行更详细的讨论。 与结构体不同,类实例没有默认的成员逐一构造器。[构造过程](./14_Initialization.html)章节会对构造器进行更详细的讨论。
<a name="structures_and_enumerations_are_value_types"></a> <a name="structures_and_enumerations_are_value_types"></a>
## 结构体和枚举是值类型 ## 结构体和枚举是值类型
@ -249,7 +253,7 @@ if tenEighty === alsoTenEighty {
* “等价于”表示两个类类型class type的常量或者变量引用同一个类实例。 * “等价于”表示两个类类型class type的常量或者变量引用同一个类实例。
* “等于”表示两个实例的值“相等”或“相同”,判定时要遵照类设计者定义定义的评判标准,因此相比于“相等”,这是一种更加合适的叫法。 * “等于”表示两个实例的值“相等”或“相同”,判定时要遵照类设计者定义定义的评判标准,因此相比于“相等”,这是一种更加合适的叫法。
当你在定义你的自定义类和结构体的时候,你有义务来决定判定两个实例“相等”的标准。在章节[运算符函数(Operator Functions)](24_Advanced_Operators.html#operator_functions)中将会详细介绍实现自定义“等于”和“不等于”运算符的流程。 当你在定义你的自定义类和结构体的时候,你有义务来决定判定两个实例“相等”的标准。在章节[等价操作符](./24_Advanced_Operators.html#equivalence_operators)中将会详细介绍实现自定义“等于”和“不等于”运算符的流程。
### 指针 ### 指针

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[shinyzhu](https://github.com/shinyzhu) > 翻译:[shinyzhu](https://github.com/shinyzhu)
> 校对:[pp-prog](https://github.com/pp-prog) [yangsiy](https://github.com/yangsiy) > 校对:[pp-prog](https://github.com/pp-prog) [yangsiy](https://github.com/yangsiy)
> 2.0
> 翻译+校对:[yangsiy](https://github.com/yangsiy)
# 属性 (Properties) # 属性 (Properties)
--- ---
@ -23,7 +27,7 @@
简单来说,一个存储属性就是存储在特定类或结构体的实例里的一个常量或变量。存储属性可以是*变量存储属性*(用关键字`var`定义),也可以是*常量存储属性*(用关键字`let`定义)。 简单来说,一个存储属性就是存储在特定类或结构体的实例里的一个常量或变量。存储属性可以是*变量存储属性*(用关键字`var`定义),也可以是*常量存储属性*(用关键字`let`定义)。
可以在定义存储属性的时候指定默认值,请参考[构造过程](../chapter2/14_Initialization.html)一章的[默认属性值](../chapter2/14_Initialization.html#default_property_values)一节。也可以在构造过程中设置或修改存储属性的值,甚至修改常量存储属性的值,请参考[构造过程](../chapter2/14_Initialization.html)一章的[在初始化阶段修改常量存储属性](../chapter2/14_Initialization.html#modifying_constant_properties_during_initialization)一节。 可以在定义存储属性的时候指定默认值,请参考[默认属性值](./14_Initialization.html#default_property_values)一节。也可以在构造过程中设置或修改存储属性的值,甚至修改常量存储属性的值,请参考[在初始化阶段修改常量存储属性](./14_Initialization.html#assigning_constant_properties_during_initialization)一节。
下面的例子定义了一个名为`FixedLengthRange`的结构体,它描述了一个在创建后无法修改值域宽度的区间: 下面的例子定义了一个名为`FixedLengthRange`的结构体,它描述了一个在创建后无法修改值域宽度的区间:
@ -87,7 +91,7 @@ class DataManager {
} }
let manager = DataManager() let manager = DataManager()
manager.data.append("Some data") manager.data.append("Some data")
manager.data.append("Some more data") manager.data.append("Some more data")
// DataImporter 实例的 importer 属性还没有被创建 // DataImporter 实例的 importer 属性还没有被创建
``` ```
@ -104,9 +108,9 @@ manager.data.append("Some more data")
print(manager.importer.fileName) print(manager.importer.fileName)
// DataImporter 实例的 importer 属性现在被创建了 // DataImporter 实例的 importer 属性现在被创建了
// 输出 "data.txt” // 输出 "data.txt”
``` ```
> 注意: > 注意:
> 如果一个被标记为`lazy`的属性在没有初始化时就同时被多个线程访问,则无法保证该属性只会被初始化一次。 > 如果一个被标记为`lazy`的属性在没有初始化时就同时被多个线程访问,则无法保证该属性只会被初始化一次。
<a name="stored_properties_and_instance_variables"></a> <a name="stored_properties_and_instance_variables"></a>
@ -219,7 +223,7 @@ print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
*属性观察器*监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,甚至新的值和现在的值相同的时候也不例外。 *属性观察器*监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,甚至新的值和现在的值相同的时候也不例外。
可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重载属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。属性重载请参考[继承](chapter/13_Inheritance.html)一章的[重载](chapter/13_Inheritance.html#overriding)。 可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重载属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。属性重载请参考[重载](./13_Inheritance.html#overriding)。
> 注意: > 注意:
> 不需要为非重载的计算属性添加属性观察器,因为可以通过它的 setter 直接监控和响应值的变化。 > 不需要为非重载的计算属性添加属性观察器,因为可以通过它的 setter 直接监控和响应值的变化。
@ -233,9 +237,9 @@ print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
类似地,`didSet`观察器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名`oldValue` 类似地,`didSet`观察器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名`oldValue`
> 注意: > 注意:
> 父类的属性在子类的构造器中被赋值时,它在父类中的`willSet`和`didSet`观察器会被调用。 > 父类的属性在子类的构造器中被赋值时,它在父类中的`willSet`和`didSet`观察器会被调用。
> 有关构造器代理的更多信息,请参考[值类型的构造器代理](chapter/14_Initialization.html#initializer_delegation_for_value_types)和[构造器链](chapter/14_Initialization.html#initialization_chain)。 > 有关构造器代理的更多信息,请参考[值类型的构造器代理](./14_Initialization.html#initializer_delegation_for_value_types)和[类的构造器代理规则](./14_Initialization.html#initializer_delegation_for_class_types)。
这里是一个`willSet``didSet`的实际例子,其中定义了一个名为`StepCounter`的类,用来统计当人步行时的总步数。这个类可以跟计步器或其他日常锻炼的统计装置的输入数据配合使用。 这里是一个`willSet``didSet`的实际例子,其中定义了一个名为`StepCounter`的类,用来统计当人步行时的总步数。这个类可以跟计步器或其他日常锻炼的统计装置的输入数据配合使用。
@ -322,13 +326,13 @@ enum SomeEnumeration {
return 6 return 6
} }
} }
class SomeClass { class SomeClass {
static var storedTypeProperty = "Some value." static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int { static var computedTypeProperty: Int {
return 27 return 27
} }
class var overrideableComputedTypeProperty: Int { class var overrideableComputedTypeProperty: Int {
return 107 return 107
} }
} }
``` ```
@ -341,12 +345,12 @@ class SomeClass {
跟实例的属性一样,类型属性的访问也是通过点运算符来进行。但是,类型属性是通过类型本身来获取和设置,而不是通过实例。比如: 跟实例的属性一样,类型属性的访问也是通过点运算符来进行。但是,类型属性是通过类型本身来获取和设置,而不是通过实例。比如:
```swift ```swift
print(SomeStructure.storedTypeProperty) print(SomeStructure.storedTypeProperty)
// 输出 "Some value." // 输出 "Some value."
SomeStructure.storedTypeProperty = "Another value." SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty) print(SomeStructure.storedTypeProperty)
// 输出 "Another value.” // 输出 "Another value.”
print(SomeEnumeration.computedTypeProperty) print(SomeEnumeration.computedTypeProperty)
// 输出 "6" // 输出 "6"
print(SomeClass.computedTypeProperty) print(SomeClass.computedTypeProperty)

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[pp-prog](https://github.com/pp-prog) > 翻译:[pp-prog](https://github.com/pp-prog)
> 校对:[zqp](https://github.com/zqp) > 校对:[zqp](https://github.com/zqp)
> 2.0
> 翻译+校对:[DianQK](https://github.com/DianQK)
# 方法Methods # 方法Methods
----------------- -----------------
@ -16,7 +20,7 @@
<a name="instance_methods"></a> <a name="instance_methods"></a>
## 实例方法 (Instance Methods) ## 实例方法 (Instance Methods)
**实例方法**是属于某个特定类、结构体或者枚举类型实例的方法。实例方法提供访问和修改实例属性的方法或提供与实例目的相关的功能,并以此来支撑实例的功能。实例方法的语法与函数完全一致,详情参见[函数](../charpter2/06_Functions.md)。 **实例方法**是属于某个特定类、结构体或者枚举类型实例的方法。实例方法提供访问和修改实例属性的方法或提供与实例目的相关的功能,并以此来支撑实例的功能。实例方法的语法与函数完全一致,详情参见[函数](./06_Functions.md)。
实例方法要写在它所属的类型的前后大括号之间。实例方法能够隐式访问它所属类型的所有的其他实例方法和属性。实例方法只能被它所属的类的某个特定实例调用。实例方法不能脱离于现存的实例而被调用。 实例方法要写在它所属的类型的前后大括号之间。实例方法能够隐式访问它所属类型的所有的其他实例方法和属性。实例方法只能被它所属的类的某个特定实例调用。实例方法不能脱离于现存的实例而被调用。
@ -60,7 +64,7 @@ class Counter {
<a name="local_and_external_parameter"></a> <a name="local_and_external_parameter"></a>
### 方法的局部参数名称和外部参数名称(Local and External Parameter Names for Methods) ### 方法的局部参数名称和外部参数名称(Local and External Parameter Names for Methods)
函数参数可以同时有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用),详情参见[函数的外部参数名](06_Functions.html)。方法参数也一样(因为方法就是函数,只是这个函数与某个类型相关联了)。 函数参数可以同时有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用),详情参见[指定外部参数名](./06_Functions.html#specifying_external_parameter_names)。方法参数也一样(因为方法就是函数,只是这个函数与某个类型相关联了)。
Swift 中的方法和 Objective-C 中的方法极其相似。像在 Objective-C 中一样Swift 中方法的名称通常用一个介词指向方法的第一个参数,比如:`with``for``by`等等。前面的`Counter`类的例子中`incrementBy(_:)`方法就是这样的。介词的使用让方法在被调用时能像一个句子一样被解读。 Swift 中的方法和 Objective-C 中的方法极其相似。像在 Objective-C 中一样Swift 中方法的名称通常用一个介词指向方法的第一个参数,比如:`with``for``by`等等。前面的`Counter`类的例子中`incrementBy(_:)`方法就是这样的。介词的使用让方法在被调用时能像一个句子一样被解读。
@ -85,8 +89,8 @@ counter.incrementBy(5, numberOfTimes: 3)
// counter 的值现在是 15 // counter 的值现在是 15
``` ```
你不必为第一个参数值再定义一个外部变量名:因为从函数名`incrementBy(_numberOfTimes:)`已经能很清楚地看出它的作用。但是第二个参数,就要被一个外部参数名称所限定,以便在方法被调用时明确它的作用。 你不必为第一个参数值再定义一个外部变量名:因为从函数名`incrementBy(_numberOfTimes:)`已经能很清楚地看出它的作用。但是第二个参数,就要被一个外部参数名称所限定,以便在方法被调用时明确它的作用。
这种默认行为使上面代码意味着:在 Swift 中定义方法使用了与 Objective-C 同样的语法风格,并且方法将以自然表达式的方式被调用。 这种默认行为使上面代码意味着:在 Swift 中定义方法使用了与 Objective-C 同样的语法风格,并且方法将以自然表达式的方式被调用。
<a name="modifying_external_parameter_name_behavior_for_methods"></a> <a name="modifying_external_parameter_name_behavior_for_methods"></a>
@ -95,7 +99,7 @@ counter.incrementBy(5, numberOfTimes: 3)
有时为方法的第一个参数提供一个外部参数名称是非常有用的,尽管这不是默认的行为。你可以自己添加一个显式的外部名称或者用一个井号(`#`)作为第一个参数的前缀来把这个局部名称当作外部名称使用。 有时为方法的第一个参数提供一个外部参数名称是非常有用的,尽管这不是默认的行为。你可以自己添加一个显式的外部名称或者用一个井号(`#`)作为第一个参数的前缀来把这个局部名称当作外部名称使用。
相反,如果你不想为方法的第二个及后续的参数提供一个外部名称,可以通过使用下划线(`_`)作为该参数的显式外部名称,这样做将覆盖默认行为。 相反,如果你不想为方法的第二个及后续的参数提供一个外部名称,可以通过使用下划线(`_`)作为该参数的显式外部名称,这样做将覆盖默认行为。
<a name="the_self_property"></a> <a name="the_self_property"></a>
### self 属性(The self Property) ### self 属性(The self Property)
@ -157,7 +161,7 @@ print("The point is now at (\(somePoint.x), \(somePoint.y))")
上面的`Point`结构体定义了一个变异方法mutating method`moveByX(_:y:)`用来移动点。`moveByX`方法在被调用时修改了这个点,而不是返回一个新的点。方法定义时加上`mutating`关键字,这才让方法可以修改值类型的属性。 上面的`Point`结构体定义了一个变异方法mutating method`moveByX(_:y:)`用来移动点。`moveByX`方法在被调用时修改了这个点,而不是返回一个新的点。方法定义时加上`mutating`关键字,这才让方法可以修改值类型的属性。
注意:不能在结构体类型常量上调用变异方法,因为常量的属性不能被改变,即使想改变的是常量的变量属性也不行,详情参见[存储属性和实例变量](10_Properties.html#global_and_local_variables) 注意:不能在结构体类型常量上调用变异方法,因为常量的属性不能被改变,即使想改变的是常量的变量属性也不行,详情参见[存储属性和实例变量](./10_Properties.html#global_and_local_variables)
```swift ```swift
let fixedPoint = Point(x: 3.0, y: 3.0) let fixedPoint = Point(x: 3.0, y: 3.0)
@ -234,23 +238,23 @@ SomeClass.someTypeMethod()
游戏初始时,所有的游戏等级(除了等级 1都被锁定。每次有玩家完成一个等级这个等级就对这个设备上的所有玩家解锁。`LevelTracker`结构体用静态属性和方法监测游戏的哪个等级已经被解锁。它还监测每个玩家的当前等级。 游戏初始时,所有的游戏等级(除了等级 1都被锁定。每次有玩家完成一个等级这个等级就对这个设备上的所有玩家解锁。`LevelTracker`结构体用静态属性和方法监测游戏的哪个等级已经被解锁。它还监测每个玩家的当前等级。
```swift ```swift
struct LevelTracker { struct LevelTracker {
static var highestUnlockedLevel = 1 static var highestUnlockedLevel = 1
static func unlockLevel(level: Int) { static func unlockLevel(level: Int) {
if level > highestUnlockedLevel { highestUnlockedLevel = level } if level > highestUnlockedLevel { highestUnlockedLevel = level }
} }
static func levelIsUnlocked(level: Int) -> Bool { static func levelIsUnlocked(level: Int) -> Bool {
return level <= highestUnlockedLevel return level <= highestUnlockedLevel
} }
var currentLevel = 1 var currentLevel = 1
mutating func advanceToLevel(level: Int) -> Bool { mutating func advanceToLevel(level: Int) -> Bool {
if LevelTracker.levelIsUnlocked(level) { if LevelTracker.levelIsUnlocked(level) {
currentLevel = level currentLevel = level
return true return true
} else { } else {
return false return false
} }
} }
} }
``` ```

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[siemenliu](https://github.com/siemenliu) > 翻译:[siemenliu](https://github.com/siemenliu)
> 校对:[zq54zquan](https://github.com/zq54zquan) > 校对:[zq54zquan](https://github.com/zq54zquan)
> 2.0
> 翻译+校对:[shanksyang](https://github.com/shanksyang)
# 下标脚本Subscripts # 下标脚本Subscripts
----------------- -----------------
@ -79,7 +83,7 @@ numberOfLegs["bird"] = 2
上例定义一个名为`numberOfLegs`的变量并用一个字典字面量初始化出了包含三对键值的字典实例。`numberOfLegs`的字典存放值类型推断为`[String:Int]`。字典实例创建完成之后通过下标脚本的方式将整型值`2`赋值到字典实例的索引为`bird`的位置中。 上例定义一个名为`numberOfLegs`的变量并用一个字典字面量初始化出了包含三对键值的字典实例。`numberOfLegs`的字典存放值类型推断为`[String:Int]`。字典实例创建完成之后通过下标脚本的方式将整型值`2`赋值到字典实例的索引为`bird`的位置中。
更多关于字典Dictionary下标脚本的信息请参考[读取和修改字典](../chapter2/04_Collection_Types.html) 更多关于字典Dictionary下标脚本的信息请参考[读取和修改字典](./04_Collection_Types.html#accessing_and_modifying_a_dictionary)
> 注意: > 注意:
> Swift 中字典的附属脚本实现中,在`get`部分返回值是`Int?`,上例中的`numberOfLegs`字典通过附属脚本返回的是一个`Int?`或者说“可选的int”不是每个字典的索引都能得到一个整型值对于没有设过值的索引的访问返回的结果就是`nil`;同样想要从字典实例中删除某个索引下的值也只需要给这个索引赋值为`nil`即可。 > Swift 中字典的附属脚本实现中,在`get`部分返回值是`Int?`,上例中的`numberOfLegs`字典通过附属脚本返回的是一个`Int?`或者说“可选的int”不是每个字典的索引都能得到一个整型值对于没有设过值的索引的访问返回的结果就是`nil`;同样想要从字典实例中删除某个索引下的值也只需要给这个索引赋值为`nil`即可。
@ -118,7 +122,7 @@ struct Matrix {
} }
``` ```
`Matrix`提供了一个两个入参的构造方法,入参分别是`rows``columns`,创建了一个足够容纳`rows * columns`个数的`Double`类型数组。通过传入数组长度和初始值0.0到数组的一个构造器,将`Matrix`中每个元素初始值0.0。关于数组的构造方法和析构方法请参考[创建并且构造一个数组](../chapter2/04_Collection_Types.html)。 `Matrix`提供了一个两个入参的构造方法,入参分别是`rows``columns`,创建了一个足够容纳`rows * columns`个数的`Double`类型数组。通过传入数组长度和初始值0.0到数组的一个构造器,将`Matrix`中每个元素初始值0.0。关于数组的构造方法和析构方法请参考[创建一个数组](./04_Collection_Types.html#creating_an_empty_array)。
你可以通过传入合适的`row``column`的数量来构造一个新的`Matrix`实例: 你可以通过传入合适的`row``column`的数量来构造一个新的`Matrix`实例:

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[Hawstein](https://github.com/Hawstein) > 翻译:[Hawstein](https://github.com/Hawstein)
> 校对:[menlongsheng](https://github.com/menlongsheng) > 校对:[menlongsheng](https://github.com/menlongsheng)
> 2.0
> 翻译+校对:[shanksyang](https://github.com/shanksyang)
# 继承Inheritance # 继承Inheritance
------------------- -------------------
@ -25,34 +29,34 @@
> 注意: > 注意:
Swift 中的类并不是从一个通用的基类继承而来。如果你不为你定义的类指定一个超类的话,这个类就自动成为基类。 Swift 中的类并不是从一个通用的基类继承而来。如果你不为你定义的类指定一个超类的话,这个类就自动成为基类。
下面的例子定义了一个叫`Vehicle`的基类。这个基类声明了一个名为`currentSpeed `默认值是0.0的存储属性(属性类型推断为`Double `)。`currentSpeed `属性的值被一个`String` 类型的只读计算型属性`description`使用,用来创建车辆的描述。 下面的例子定义了一个叫`Vehicle`的基类。这个基类声明了一个名为`currentSpeed `默认值是0.0的存储属性(属性类型推断为`Double `)。`currentSpeed `属性的值被一个`String` 类型的只读计算型属性`description`使用,用来创建车辆的描述。
`Vehicle`基类也定义了一个名为`makeNoise`的方法。这个方法实际上不为`Vehicle`实例做任何事,但之后将会被`Vehicle`的子类定制: `Vehicle`基类也定义了一个名为`makeNoise`的方法。这个方法实际上不为`Vehicle`实例做任何事,但之后将会被`Vehicle`的子类定制:
```swift ```swift
class Vehicle { class Vehicle {
var currentSpeed = 0.0 var currentSpeed = 0.0
var description: String { var description: String {
return "traveling at \(currentSpeed) miles per hour" return "traveling at \(currentSpeed) miles per hour"
} }
func makeNoise() { func makeNoise() {
// 什么也不做-因为车辆不一定会有噪音 // 什么也不做-因为车辆不一定会有噪音
} }
} }
``` ```
您可以用初始化语法创建一个`Vehicle `的新实例,即类名后面跟一个空括号: 您可以用初始化语法创建一个`Vehicle `的新实例,即类名后面跟一个空括号:
```swift ```swift
let someVehicle = Vehicle() let someVehicle = Vehicle()
``` ```
现在已经创建了一个`Vehicle`的新实例,你可以访问它的`description`属性来打印车辆的当前速度。 现在已经创建了一个`Vehicle`的新实例,你可以访问它的`description`属性来打印车辆的当前速度。
```swift ```swift
print("Vehicle: \(someVehicle.description)") print("Vehicle: \(someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour // Vehicle: traveling at 0.0 miles per hour
``` ```
`Vehicle`类定义了一个通用特性的车辆类,实际上没什么用处。为了让它变得更加有用,需要改进它能够描述一个更加具体的车辆类。 `Vehicle`类定义了一个通用特性的车辆类,实际上没什么用处。为了让它变得更加有用,需要改进它能够描述一个更加具体的车辆类。
<a name="subclassing"></a> <a name="subclassing"></a>
@ -68,51 +72,51 @@ class SomeClass: SomeSuperclass {
} }
``` ```
下一个例子,定义一个叫`Bicycle`的子类,继承成父类`Vehicle` 下一个例子,定义一个叫`Bicycle`的子类,继承成父类`Vehicle`
```swift
class Bicycle: Vehicle {
var hasBasket = false
}
```
新的`Bicycle`类自动获得`Vehicle`类的所有特性,比如 `currentSpeed ``description`属性,还有它的`makeNoise`方法。 ```swift
class Bicycle: Vehicle {
除了它所继承的特性,`Bicycle`类还定义了一个默认值为`false`的存储型属性`hasBasket`(属性推断为`Bool`)。 var hasBasket = false
}
默认情况下,你创建任何新的`Bicycle`实例将不会有一个篮子,创建该实例之后,你可以为特定的`Bicycle`实例设置`hasBasket `属性为`ture` ```
```swift 新的`Bicycle`类自动获得`Vehicle`类的所有特性,比如 `currentSpeed ``description`属性,还有它的`makeNoise`方法。
let bicycle = Bicycle()
bicycle.hasBasket = true 除了它所继承的特性,`Bicycle`类还定义了一个默认值为`false`的存储型属性`hasBasket`(属性推断为`Bool`)。
```
默认情况下,你创建任何新的`Bicycle`实例将不会有一个篮子,创建该实例之后,你可以为特定的`Bicycle`实例设置`hasBasket `属性为`ture`
你还可以修改`Bicycle `实例所继承的`currentSpeed `属性,和查询实例所继承的`description `属性:
```swift
```swift let bicycle = Bicycle()
bicycle.currentSpeed = 15.0 bicycle.hasBasket = true
print("Bicycle: \(bicycle.description)") ```
// Bicycle: traveling at 15.0 miles per hour
你还可以修改`Bicycle `实例所继承的`currentSpeed `属性,和查询实例所继承的`description `属性:
```swift
bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour
``` ```
子类还可以继续被其它类继承,下面的示例为`Bicycle `创建了一个名为`Tandem `(双人自行车)的子类: 子类还可以继续被其它类继承,下面的示例为`Bicycle `创建了一个名为`Tandem `(双人自行车)的子类:
```swift ```swift
class Tandem: Bicycle { class Tandem: Bicycle {
var currentNumberOfPassengers = 0 var currentNumberOfPassengers = 0
} }
``` ```
`Tandem``Bicycle`继承了所有的属性与方法,这又使它同时继承了`Vehicle`的所有属性与方法。`Tandem`也增加了一个新的叫做`currentNumberOfPassengers`的存储型属性默认值为0。 `Tandem``Bicycle`继承了所有的属性与方法,这又使它同时继承了`Vehicle`的所有属性与方法。`Tandem`也增加了一个新的叫做`currentNumberOfPassengers`的存储型属性默认值为0。
如果你创建了一个`Tandem`的实例,你可以使用它所有的新属性和继承的属性,还能查询从`Vehicle`继承来的只读属性`description ` 如果你创建了一个`Tandem`的实例,你可以使用它所有的新属性和继承的属性,还能查询从`Vehicle`继承来的只读属性`description `
```swift ```swift
let tandem = Tandem() let tandem = Tandem()
tandem.hasBasket = true tandem.hasBasket = true
tandem.currentNumberOfPassengers = 2 tandem.currentNumberOfPassengers = 2
tandem.currentSpeed = 22.0 tandem.currentSpeed = 22.0
print("Tandem: \(tandem.description)") print("Tandem: \(tandem.description)")
// Tandem: traveling at 22.0 miles per hour // Tandem: traveling at 22.0 miles per hour
``` ```
@ -142,18 +146,18 @@ print("Tandem: \(tandem.description)")
下面的例子定义了`Vehicle`的一个新的子类,叫`Train `,它重写了从`Vehicle`类继承来的`makeNoise `方法: 下面的例子定义了`Vehicle`的一个新的子类,叫`Train `,它重写了从`Vehicle`类继承来的`makeNoise `方法:
```swift ```swift
class Train: Vehicle { class Train: Vehicle {
override func makeNoise() { override func makeNoise() {
print("Choo Choo") print("Choo Choo")
} }
} }
``` ```
如果你创建一个`Train `的新实例,并调用了它的`makeNoise `方法,你就会发现`Train `版本的方法被调用: 如果你创建一个`Train `的新实例,并调用了它的`makeNoise `方法,你就会发现`Train `版本的方法被调用:
```swift ```swift
let train = Train() let train = Train()
train.makeNoise() train.makeNoise()
// prints "Choo Choo" // prints "Choo Choo"
``` ```
@ -173,23 +177,23 @@ train.makeNoise()
以下的例子定义了一个新类,叫`Car`,它是`Vehicle `的子类。这个类引入了一个新的存储型属性叫做`gear `默认为整数1。`Car`类重写了继承自`Vehicle `的description属性提供自定义的包含当前档位的描述 以下的例子定义了一个新类,叫`Car`,它是`Vehicle `的子类。这个类引入了一个新的存储型属性叫做`gear `默认为整数1。`Car`类重写了继承自`Vehicle `的description属性提供自定义的包含当前档位的描述
```swift ```swift
class Car: Vehicle { class Car: Vehicle {
var gear = 1 var gear = 1
override var description: String { override var description: String {
return super.description + " in gear \(gear)" return super.description + " in gear \(gear)"
} }
} }
``` ```
重写的`description `属性,首先要调用`super.description`返回`Vehicle`类的`description`属性。之后,`Car `类版本的`description`在末尾增加了一些额外的文本来提供关于当前档位的信息。 重写的`description `属性,首先要调用`super.description`返回`Vehicle`类的`description`属性。之后,`Car `类版本的`description`在末尾增加了一些额外的文本来提供关于当前档位的信息。
如果你创建了`Car `的实例并且设置了它的`gear``currentSpeed`属性,你可以看到它的`description`返回了`Car`中定义的`description` 如果你创建了`Car `的实例并且设置了它的`gear``currentSpeed`属性,你可以看到它的`description`返回了`Car`中定义的`description`
```swift ```swift
let car = Car() let car = Car()
car.currentSpeed = 25.0 car.currentSpeed = 25.0
car.gear = 3 car.gear = 3
print("Car: \(car.description)") print("Car: \(car.description)")
// Car: traveling at 25.0 miles per hour in gear 3 // Car: traveling at 25.0 miles per hour in gear 3
``` ```
@ -203,21 +207,21 @@ print("Car: \(car.description)")
下面的例子定义了一个新类叫`AutomaticCar`,它是`Car`的子类。`AutomaticCar`表示自动挡汽车,它可以根据当前的速度自动选择合适的挡位: 下面的例子定义了一个新类叫`AutomaticCar`,它是`Car`的子类。`AutomaticCar`表示自动挡汽车,它可以根据当前的速度自动选择合适的挡位:
```swift ```swift
class AutomaticCar: Car { class AutomaticCar: Car {
override var currentSpeed: Double { override var currentSpeed: Double {
didSet { didSet {
gear = Int(currentSpeed / 10.0) + 1 gear = Int(currentSpeed / 10.0) + 1
} }
} }
} }
``` ```
当你设置`AutomaticCar``currentSpeed `属性,属性的`didSet`观察器就会自动地设置`gear`属性为新的速度选择一个合适的挡位。具体来说就是属性观察器将新的速度值除以10然后向下取得最接近的整数值最后加1来得到档位`gear`的值。例如速度为10.0时挡位为1速度为35.0时挡位为4 当你设置`AutomaticCar``currentSpeed `属性,属性的`didSet`观察器就会自动地设置`gear`属性为新的速度选择一个合适的挡位。具体来说就是属性观察器将新的速度值除以10然后向下取得最接近的整数值最后加1来得到档位`gear`的值。例如速度为10.0时挡位为1速度为35.0时挡位为4
```swift ```swift
let automatic = AutomaticCar() let automatic = AutomaticCar()
automatic.currentSpeed = 35.0 automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)") print("AutomaticCar: \(automatic.description)")
// AutomaticCar: traveling at 35.0 miles per hour in gear 4 // AutomaticCar: traveling at 35.0 miles per hour in gear 4
``` ```

View File

@ -1,5 +1,9 @@
> 1.0
> 翻译:[lifedim](https://github.com/lifedim) > 翻译:[lifedim](https://github.com/lifedim)
> 校对:[lifedim](https://github.com/lifedim)[chenmingbiao](https://github.com/chenmingbiao) > 校对:[lifedim](https://github.com/lifedim)
> 2.0
> 翻译+校对:[chenmingbiao](https://github.com/chenmingbiao)
# 构造过程Initialization # 构造过程Initialization
@ -21,7 +25,7 @@
构造过程是通过定义构造器(`Initializers`)来实现的,这些构造器可以看做是用来创建特定类型实例的特殊方法。与 Objective-C 中的构造器不同Swift 的构造器无需返回值,它们的主要任务是保证新实例在第一次使用前完成正确的初始化。 构造过程是通过定义构造器(`Initializers`)来实现的,这些构造器可以看做是用来创建特定类型实例的特殊方法。与 Objective-C 中的构造器不同Swift 的构造器无需返回值,它们的主要任务是保证新实例在第一次使用前完成正确的初始化。
类的实例也可以通过定义析构器(`deinitializer`)在实例释放之前执行特定的清除工作。想了解更多关于析构器的内容,请参考[析构过程](15_Deinitialization.html)。 类的实例也可以通过定义析构器(`deinitializer`)在实例释放之前执行特定的清除工作。想了解更多关于析构器的内容,请参考[析构过程](./15_Deinitialization.html)。
<a name="setting_initial_values_for_stored_properties"></a> <a name="setting_initial_values_for_stored_properties"></a>
## 存储型属性的初始赋值 ## 存储型属性的初始赋值
@ -193,6 +197,7 @@ cheeseQuestion.response = "Yes, I do like cheese."
调查问题在问题提出之后,我们才能得到回答。所以我们将属性回答`response`声明为`String?`类型,或者说是可选字符串类型`optional String`。当`SurveyQuestion`实例化时,它将自动赋值为空`nil`,表明暂时还不存在此字符串。 调查问题在问题提出之后,我们才能得到回答。所以我们将属性回答`response`声明为`String?`类型,或者说是可选字符串类型`optional String`。当`SurveyQuestion`实例化时,它将自动赋值为空`nil`,表明暂时还不存在此字符串。
<a name="assigning_constant_properties_during_initialization"></a>
### 构造过程中常量属性的修改 ### 构造过程中常量属性的修改
只要在构造过程结束前常量的值能确定,你可以在构造过程中的任意时间点修改常量属性的值。 只要在构造过程结束前常量的值能确定,你可以在构造过程中的任意时间点修改常量属性的值。
@ -237,6 +242,7 @@ var item = ShoppingListItem()
由于`ShoppingListItem`类中的所有属性都有默认值,且它是没有父类的基类,它将自动获得一个可以为所有属性设置默认值的默认构造器(尽管代码中没有显式为`name`属性设置默认值,但由于`name`是可选字符串类型,它将默认设置为`nil`)。上面例子中使用默认构造器创造了一个`ShoppingListItem`类的实例(使用`ShoppingListItem()`形式的构造器语法),并将其赋值给变量`item` 由于`ShoppingListItem`类中的所有属性都有默认值,且它是没有父类的基类,它将自动获得一个可以为所有属性设置默认值的默认构造器(尽管代码中没有显式为`name`属性设置默认值,但由于`name`是可选字符串类型,它将默认设置为`nil`)。上面例子中使用默认构造器创造了一个`ShoppingListItem`类的实例(使用`ShoppingListItem()`形式的构造器语法),并将其赋值给变量`item`
<a name="memberwise_initializers_for_structure_types"></a>
### 结构体的逐一成员构造器 ### 结构体的逐一成员构造器
除上面提到的默认构造器,如果结构体对所有存储型属性提供了默认值且自身没有提供定制的构造器,它们能自动获得一个逐一成员构造器。 除上面提到的默认构造器,如果结构体对所有存储型属性提供了默认值且自身没有提供定制的构造器,它们能自动获得一个逐一成员构造器。
@ -259,14 +265,14 @@ let twoByTwo = Size(width: 2.0, height: 2.0)
构造器可以通过调用其它构造器来完成实例的部分构造过程。这一过程称为构造器代理,它能减少多个构造器间的代码重复。 构造器可以通过调用其它构造器来完成实例的部分构造过程。这一过程称为构造器代理,它能减少多个构造器间的代码重复。
构造器代理的实现规则和形式在值类型和类类型中有所不同。值类型(结构体和枚举类型)不支持继承,所以构造器代理的过程相对简单,因为它们只能代理给本身提供的其它构造器。类则不同,它可以继承自其它类(请参考[继承](13_Inheritance.html)),这意味着类有责任保证其所有继承的存储型属性在构造时也能正确的初始化。这些责任将在后续章节[类的继承和构造过程](#class_inheritance_and_initialization)中介绍。 构造器代理的实现规则和形式在值类型和类类型中有所不同。值类型(结构体和枚举类型)不支持继承,所以构造器代理的过程相对简单,因为它们只能代理给本身提供的其它构造器。类则不同,它可以继承自其它类(请参考[继承](./13_Inheritance.html)),这意味着类有责任保证其所有继承的存储型属性在构造时也能正确的初始化。这些责任将在后续章节[类的继承和构造过程](#class_inheritance_and_initialization)中介绍。
对于值类型,你可以使用`self.init`在自定义的构造器中引用其它的属于相同值类型的构造器。并且你只能在构造器内部调用`self.init` 对于值类型,你可以使用`self.init`在自定义的构造器中引用其它的属于相同值类型的构造器。并且你只能在构造器内部调用`self.init`
如果你为某个值类型定义了一个定制的构造器,你将无法访问到默认构造器(如果是结构体,则无法访问逐一对象构造器)。这个限制可以防止你在为值类型定义了一个更复杂的,完成了重要准备构造器之后,别人还是错误的使用了那个自动生成的构造器。 如果你为某个值类型定义了一个定制的构造器,你将无法访问到默认构造器(如果是结构体,则无法访问逐一对象构造器)。这个限制可以防止你在为值类型定义了一个更复杂的,完成了重要准备构造器之后,别人还是错误的使用了那个自动生成的构造器。
>注意: >注意:
假如你想通过默认构造器、逐一对象构造器以及你自己定制的构造器为值类型创建实例,我们建议你将自己定制的构造器写到扩展(`extension`)中,而不是跟值类型定义混在一起。想查看更多内容,请查看[扩展](20_Extensions.html)章节。 假如你想通过默认构造器、逐一对象构造器以及你自己定制的构造器为值类型创建实例,我们建议你将自己定制的构造器写到扩展(`extension`)中,而不是跟值类型定义混在一起。想查看更多内容,请查看[扩展](./20_Extensions.html)章节。
下面例子将定义一个结构体`Rect`,用来代表几何矩形。这个例子需要两个辅助的结构体`Size``Point`,它们各自为其所有的属性提供了初始值`0.0` 下面例子将定义一个结构体`Rect`,用来代表几何矩形。这个例子需要两个辅助的结构体`Size``Point`,它们各自为其所有的属性提供了初始值`0.0`
@ -324,7 +330,7 @@ let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
构造器`init(center:size:)`可以自己将`origin``size`的新值赋值到对应的属性中。然而尽量利用现有的构造器和它所提供的功能来实现`init(center:size:)`的功能,是更方便、更清晰和更直观的方法。 构造器`init(center:size:)`可以自己将`origin``size`的新值赋值到对应的属性中。然而尽量利用现有的构造器和它所提供的功能来实现`init(center:size:)`的功能,是更方便、更清晰和更直观的方法。
>注意: >注意:
如果你想用另外一种不需要自己定义`init()``init(origin:size:)`的方式来实现这个例子,请参考[扩展](20_Extensions.html)。 如果你想用另外一种不需要自己定义`init()``init(origin:size:)`的方式来实现这个例子,请参考[扩展](./20_Extensions.html)。
<a name="class_inheritance_and_initialization"></a> <a name="class_inheritance_and_initialization"></a>
## 类的继承和构造过程 ## 类的继承和构造过程
@ -361,8 +367,8 @@ convenience init(parameters) {
} }
``` ```
<a name="initialization_chain"></a> <a name="initializer_delegation_for_class_types"></a>
### 构造器 ### 类的构造器代理规则
为了简化指定构造器和便利构造器之间的调用关系Swift 采用以下三条规则来限制构造器之间的代理调用: 为了简化指定构造器和便利构造器之间的调用关系Swift 采用以下三条规则来限制构造器之间的代理调用:
@ -465,6 +471,7 @@ Swift 编译器将执行 4 种有效的安全检查,以确保两段式构造
最终,一旦子类的指定构造器完成调用,最开始被调用的便利构造器可以执行更多的定制操作。 最终,一旦子类的指定构造器完成调用,最开始被调用的便利构造器可以执行更多的定制操作。
<a name="initializer_inheritance_and_overriding"></a>
### 构造器的继承和重载 ### 构造器的继承和重载
跟 Objective-C 中的子类不同Swift 中的子类不会默认继承父类的构造器。Swift 的这种机制可以防止一个父类的简单构造器被一个更专业的子类继承,并被错误的用来创建子类的实例。 跟 Objective-C 中的子类不同Swift 中的子类不会默认继承父类的构造器。Swift 的这种机制可以防止一个父类的简单构造器被一个更专业的子类继承,并被错误的用来创建子类的实例。
@ -609,7 +616,7 @@ class RecipeIngredient: Food {
`RecipeIngredient`也定义了一个便利构造器`init(name: String)`,它只通过`name`来创建`RecipeIngredient`的实例。这个便利构造器假设任意`RecipeIngredient`实例的`quantity`为1所以不需要显示指明数量即可创建出实例。这个便利构造器的定义可以让创建实例更加方便和快捷并且避免了使用重复的代码来创建多个`quantity`为 1 的`RecipeIngredient`实例。这个便利构造器只是简单的将任务代理给了同一类里提供的指定构造器。 `RecipeIngredient`也定义了一个便利构造器`init(name: String)`,它只通过`name`来创建`RecipeIngredient`的实例。这个便利构造器假设任意`RecipeIngredient`实例的`quantity`为1所以不需要显示指明数量即可创建出实例。这个便利构造器的定义可以让创建实例更加方便和快捷并且避免了使用重复的代码来创建多个`quantity`为 1 的`RecipeIngredient`实例。这个便利构造器只是简单的将任务代理给了同一类里提供的指定构造器。
注意,`RecipeIngredient`的便利构造器`init(name: String)`使用了跟`Food`中指定构造器`init(name: String)`相同的参数。因为这个便利构造器重写要父类的指定构造器`init(name: String)`,必须在前面使用使用`override`标识。 注意,`RecipeIngredient`的便利构造器`init(name: String)`使用了跟`Food`中指定构造器`init(name: String)`相同的参数。因为这个便利构造器重写要父类的指定构造器`init(name: String)`,必须在前面使用使用`override`标识(参见[构造器的继承和重载](#initializer_inheritance_and_overriding)
在这个例子中,`RecipeIngredient`的父类是`Food`,它有一个便利构造器`init()`。这个构造器因此也被`RecipeIngredient`继承。这个继承的`init()`函数版本跟`Food`提供的版本是一样的,除了它是将任务代理给`RecipeIngredient`版本的`init(name: String)`而不是`Food`提供的版本。 在这个例子中,`RecipeIngredient`的父类是`Food`,它有一个便利构造器`init()`。这个构造器因此也被`RecipeIngredient`继承。这个继承的`init()`函数版本跟`Food`提供的版本是一样的,除了它是将任务代理给`RecipeIngredient`版本的`init(name: String)`而不是`Food`提供的版本。

View File

@ -1,5 +1,9 @@
> 1.0
> 翻译:[bruce0505](https://github.com/bruce0505) > 翻译:[bruce0505](https://github.com/bruce0505)
> 校对:[fd5788](https://github.com/fd5788)[chenmingbiao](https://github.com/chenmingbiao) > 校对:[fd5788](https://github.com/fd5788)
> 2.0
> 翻译+校对:[chenmingbiao](https://github.com/chenmingbiao)
# 析构过程Deinitialization # 析构过程Deinitialization
--------------------------- ---------------------------
@ -14,7 +18,7 @@
<a name="how_deinitialization_works"></a> <a name="how_deinitialization_works"></a>
##析构过程原理 ##析构过程原理
Swift 会自动释放不再需要的实例以释放资源。如[自动引用计数](16_Automatic_Reference_Counting.html)章节中所讲述Swift 通过`自动引用计数ARC`处理实例的内存管理。通常当你的实例被释放时不需要手动地去清理。但是,当使用自己的资源时,你可能需要进行一些额外的清理。例如,如果创建了一个自定义的类来打开一个文件,并写入一些数据,你可能需要在类实例被释放之前手动去关闭该文件。 Swift 会自动释放不再需要的实例以释放资源。如[自动引用计数](./16_Automatic_Reference_Counting.html)章节中所讲述Swift 通过`自动引用计数ARC`处理实例的内存管理。通常当你的实例被释放时不需要手动地去清理。但是,当使用自己的资源时,你可能需要进行一些额外的清理。例如,如果创建了一个自定义的类来打开一个文件,并写入一些数据,你可能需要在类实例被释放之前手动去关闭该文件。
在类的定义中,每个类最多只能有一个析构器,而且析构器不带任何参数,如下所示: 在类的定义中,每个类最多只能有一个析构器,而且析构器不带任何参数,如下所示:

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[TimothyYe](https://github.com/TimothyYe) > 翻译:[TimothyYe](https://github.com/TimothyYe)
> 校对:[Hawstein](https://github.com/Hawstein) > 校对:[Hawstein](https://github.com/Hawstein)
> 2.0
> 翻译+校对:[Channe](https://github.com/Channe)
# 自动引用计数 # 自动引用计数
----------------- -----------------
@ -23,8 +27,8 @@ Swift 使用自动引用计数ARC机制来跟踪和管理你的应用程
<a name="how_arc_works"></a> <a name="how_arc_works"></a>
## 自动引用计数的工作机制 ## 自动引用计数的工作机制
当你每次创建一个类的新的实例的时候ARC 会分配一大块内存用来储存实例的信息。内存中会包含实例的类型信息,以及这个实例所有相关属性的值。 当你每次创建一个类的新的实例的时候ARC 会分配一大块内存用来储存实例的信息。内存中会包含实例的类型信息,以及这个实例所有相关属性的值。
此外当实例不再被使用时ARC 释放实例所占用的内存,并让释放的内存能挪作他用。这确保了不再被使用的实例,不会一直占用内存空间。 此外当实例不再被使用时ARC 释放实例所占用的内存,并让释放的内存能挪作他用。这确保了不再被使用的实例,不会一直占用内存空间。
然而,当 ARC 收回和释放了正在被使用中的实例,该实例的属性和方法将不能再被访问和调用。实际上,如果你试图访问这个实例,你的应用程序很可能会崩溃。 然而,当 ARC 收回和释放了正在被使用中的实例,该实例的属性和方法将不能再被访问和调用。实际上,如果你试图访问这个实例,你的应用程序很可能会崩溃。
@ -86,8 +90,8 @@ reference3 = reference1
```swift ```swift
reference1 = nil reference1 = nil
reference2 = nil reference2 = nil
``` ```
在你清楚地表明不再使用这个`Person`实例时即第三个也就是最后一个强引用被断开时ARC 会销毁它。 在你清楚地表明不再使用这个`Person`实例时即第三个也就是最后一个强引用被断开时ARC 会销毁它。
```swift ```swift
@ -158,7 +162,7 @@ number73!.tenant = john
在将两个实例联系在一起之后,强引用的关系如图所示: 在将两个实例联系在一起之后,强引用的关系如图所示:
![](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/referenceCycle02_2x.png) ![](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/referenceCycle02_2x.png)
不幸的是,这两个实例关联后会产生一个循环强引用。`Person`实例现在有了一个指向`Apartment`实例的强引用,而`Apartment`实例也有了一个指向`Person`实例的强引用。因此,当你断开`john``number73`变量所持有的强引用时,引用计数并不会降为 0实例也不会被 ARC 销毁: 不幸的是,这两个实例关联后会产生一个循环强引用。`Person`实例现在有了一个指向`Apartment`实例的强引用,而`Apartment`实例也有了一个指向`Person`实例的强引用。因此,当你断开`john``number73`变量所持有的强引用时,引用计数并不会降为 0实例也不会被 ARC 销毁:
```swift ```swift
@ -184,7 +188,7 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的
对于生命周期中会变为`nil`的实例使用弱引用。相反地,对于初始化赋值后再也不会被赋值为`nil`的实例,使用无主引用。 对于生命周期中会变为`nil`的实例使用弱引用。相反地,对于初始化赋值后再也不会被赋值为`nil`的实例,使用无主引用。
### 弱引用 ### 弱引用
弱引用不会对其引用的实例保持强引用,因而不会阻止 ARC 销毁被引用的实例。这个特性阻止了引用变为循环强引用。声明属性或者变量时,在前面加上`weak`关键字表明这是一个弱引用。 弱引用不会对其引用的实例保持强引用,因而不会阻止 ARC 销毁被引用的实例。这个特性阻止了引用变为循环强引用。声明属性或者变量时,在前面加上`weak`关键字表明这是一个弱引用。
在实例的生命周期中,如果某些时候引用没有值,那么弱引用可以避免循环强引用。如果引用总是有值,则可以使用无主引用,在[无主引用](#2)中有描述。在上面`Apartment`的例子中,一个公寓的生命周期中,有时是没有“居民”的,因此适合使用弱引用来解决循环强引用。 在实例的生命周期中,如果某些时候引用没有值,那么弱引用可以避免循环强引用。如果引用总是有值,则可以使用无主引用,在[无主引用](#2)中有描述。在上面`Apartment`的例子中,一个公寓的生命周期中,有时是没有“居民”的,因此适合使用弱引用来解决循环强引用。
@ -297,9 +301,9 @@ class CreditCard {
} }
deinit { print("Card #\(number) is being deinitialized") } deinit { print("Card #\(number) is being deinitialized") }
} }
``` ```
> 注意: > 注意:
> `CreditCard`类的`number`属性被定义为`UInt64`类型而不是`Int`类型,以确保`number`属性的存储量在32位和64位系统上都能足够容纳16位的卡号。 > `CreditCard`类的`number`属性被定义为`UInt64`类型而不是`Int`类型,以确保`number`属性的存储量在32位和64位系统上都能足够容纳16位的卡号。
下面的代码片段定义了一个叫`john`的可选类型`Customer`变量,用来保存某个特定客户的引用。由于是可选类型,所以变量被初始化为`nil` 下面的代码片段定义了一个叫`john`的可选类型`Customer`变量,用来保存某个特定客户的引用。由于是可选类型,所以变量被初始化为`nil`
@ -335,6 +339,8 @@ john = nil
最后的代码展示了在`john`变量被设为`nil``Customer`实例和`CreditCard`实例的构造函数都打印出了“销毁”的信息。 最后的代码展示了在`john`变量被设为`nil``Customer`实例和`CreditCard`实例的构造函数都打印出了“销毁”的信息。
<a name="unowned_references_and_implicitly_unwrapped_optional_properties"></a>
###无主引用以及隐式解析可选属性 ###无主引用以及隐式解析可选属性
上面弱引用和无主引用的例子涵盖了两种常用的需要打破循环强引用的场景。 上面弱引用和无主引用的例子涵盖了两种常用的需要打破循环强引用的场景。
@ -373,9 +379,9 @@ class City {
为了建立两个类的依赖关系,`City`的构造函数有一个`Country`实例的参数,并且将实例保存为`country`属性。 为了建立两个类的依赖关系,`City`的构造函数有一个`Country`实例的参数,并且将实例保存为`country`属性。
`Country`的构造函数调用了`City`的构造函数。然而,只有`Country`的实例完全初始化完后,`Country`的构造函数才能把`self`传给`City`的构造函数。([两段式构造过程中有具体描述](14_Initialization.html) `Country`的构造函数调用了`City`的构造函数。然而,只有`Country`的实例完全初始化完后,`Country`的构造函数才能把`self`传给`City`的构造函数。([两段式构造过程](./14_Initialization.html#two_phase_initialization)中有具体描述
为了满足这种需求,通过在类型结尾处加上感叹号(`City!`)的方式,将`Country``capitalCity`属性声明为隐式解析可选类型的属性。这表示像其他可选类型一样,`capitalCity`属性的默认值为`nil`,但是不需要展开它的值就能访问它。([隐式解析可选类型中有描述](01_The_Basics.html) 为了满足这种需求,通过在类型结尾处加上感叹号(`City!`)的方式,将`Country``capitalCity`属性声明为隐式解析可选类型的属性。这表示像其他可选类型一样,`capitalCity`属性的默认值为`nil`,但是不需要展开它的值就能访问它。([隐式解析可选类型](./01_The_Basics.html#implicityly_unwrapped_optionals)中有描述
由于`capitalCity`默认值为`nil`,一旦`Country`的实例在构造函数中给`name`属性赋值后,整个初始化过程就完成了。这代表一旦`name`属性被赋值后,`Country`的构造函数就能引用并传递隐式的`self``Country`的构造函数在赋值`capitalCity`时,就能将`self`作为参数传递给`City`的构造函数。 由于`capitalCity`默认值为`nil`,一旦`Country`的实例在构造函数中给`name`属性赋值后,整个初始化过程就完成了。这代表一旦`name`属性被赋值后,`Country`的构造函数就能引用并传递隐式的`self``Country`的构造函数在赋值`capitalCity`时,就能将`self`作为参数传递给`City`的构造函数。
@ -456,7 +462,7 @@ print(paragraph!.asHTML())
![](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/closureReferenceCycle01_2x.png) ![](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/closureReferenceCycle01_2x.png)
实例的`asHTML`属性持有闭包的强引用。但是,闭包在其闭包体内使用了`self`(引用了`self.name``self.text`),因此闭包捕获了`self`,这意味着闭包又反过来持有了`HTMLElement`实例的强引用。这样两个对象就产生了循环强引用。(更多关于闭包捕获值的信息,请参考[值捕获](07_Closures.html))。 实例的`asHTML`属性持有闭包的强引用。但是,闭包在其闭包体内使用了`self`(引用了`self.name``self.text`),因此闭包捕获了`self`,这意味着闭包又反过来持有了`HTMLElement`实例的强引用。这样两个对象就产生了循环强引用。(更多关于闭包捕获值的信息,请参考[值捕获](./07_Closures.html#capturing_values))。
>注意: >注意:
虽然闭包多次使用了`self`,它只捕获`HTMLElement`实例的一个强引用。 虽然闭包多次使用了`self`,它只捕获`HTMLElement`实例的一个强引用。
@ -477,9 +483,9 @@ paragraph = nil
>注意: >注意:
Swift 有如下要求:只要在闭包内使用`self`的成员,就要用`self.someProperty`或者`self.someMethod`(而不只是`someProperty``someMethod`)。这提醒你可能会一不小心就捕获了`self` Swift 有如下要求:只要在闭包内使用`self`的成员,就要用`self.someProperty`或者`self.someMethod`(而不只是`someProperty``someMethod`)。这提醒你可能会一不小心就捕获了`self`
###定义捕获列表 ###定义捕获列表
捕获列表中的每一项都由一对元素组成,一个元素是`weak``unowned`关键字,另一个元素是类实例的引用(如`self`)或初始化过的变量(如`delegate = self.delegate!`)。这些项在方括号中用逗号分开。 捕获列表中的每一项都由一对元素组成,一个元素是`weak``unowned`关键字,另一个元素是类实例的引用(如`self`)或初始化过的变量(如`delegate = self.delegate!`)。这些项在方括号中用逗号分开。
如果闭包有参数列表和返回类型,把捕获列表放在它们前面: 如果闭包有参数列表和返回类型,把捕获列表放在它们前面:

View File

@ -1,8 +1,12 @@
# Optional Chaining # 可空链式调用
> 1.0
> 翻译:[Jasonbroker](https://github.com/Jasonbroker) > 翻译:[Jasonbroker](https://github.com/Jasonbroker)
> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai) > 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[lyojo](https://github.com/lyojo)
----------------- -----------------
可空链式调用Optional Chaining是一种可以请求和调用属性、方法及下标的过程它的可空性体现于请求或调用的目标当前可能为空nil。如果可空的目标有值那么调用就会成功如果选择的目标为空nil那么这种调用将返回空nil。多个连续的调用可以被链接在一起形成一个调用链如果其中任何一个节点为空nil将导致整个链调用失败。 可空链式调用Optional Chaining是一种可以请求和调用属性、方法及下标的过程它的可空性体现于请求或调用的目标当前可能为空nil。如果可空的目标有值那么调用就会成功如果选择的目标为空nil那么这种调用将返回空nil。多个连续的调用可以被链接在一起形成一个调用链如果其中任何一个节点为空nil将导致整个链调用失败。
@ -10,166 +14,208 @@
注意: 注意:
Swift 的可空链式调用和 Objective-C 中的消息为空有些相像,但是 Swift 可以使用在任意类型中,并且能够检查调用是否成功。 Swift 的可空链式调用和 Objective-C 中的消息为空有些相像,但是 Swift 可以使用在任意类型中,并且能够检查调用是否成功。
##可空链式调用作为强制展开的另一个方案 <a name="optional_chaining_as_an_alternative_to_forced_unwrapping"></a>
##使用可空链式调用来强制展开
通过在想调用非空的属性、方法、或下标的可空值optional value后面放一个问号可以定义一个可空链。这一点很像在可空值后面放一个叹号来强制展开其中值。它们的主要的区别在于当可空值为空时可空链式只是调用失败然而强制展开将会触发运行时错误。 通过在想调用非空的属性、方法、或下标的可空值optional value后面放一个问号可以定义一个可空链。这一点很像在可空值后面放一个叹号来强制展开其中值。它们的主要的区别在于当可空值为空时可空链式只是调用失败然而强制展开将会触发运行时错误。
为了反映可空链式调用可以在空对象nil上调用不论这个调用的属性、方法、下标等返回的值是不是可空值它的返回结果都是一个可空值。你可以利用这个返回值来判断你的可空链式调用是否调用成功如果调用有返回值则说明调用成功返回nil则说明调用失败。 为了反映可空链式调用可以在空对象nil上调用不论这个调用的属性、方法、下标等返回的值是不是可空值它的返回结果都是一个可空值。你可以利用这个返回值来判断你的可空链式调用是否调用成功如果调用有返回值则说明调用成功返回`nil`则说明调用失败。
特别地可空链式调用的返回结果与原本的返回结果具有相同的类型但是被包装成了一个可空类型值。当可空链式调用成功时一个本应该返回Int的类型的结果将会返回Int?类型。 特别地,可空链式调用的返回结果与原本的返回结果具有相同的类型,但是被包装成了一个可空类型值。当可空链式调用成功时,一个本应该返回`Int`的类型的结果将会返回`Int?`类型。
下面几段代码将解释可空链式调用和强制展开的不同。 下面几段代码将解释可空链式调用和强制展开的不同。
首先定义两个类PersonResidence。 首先定义两个类`Person``Residence`
class Person { ```swift
class Person {
var residence: Residence? var residence: Residence?
} }
class Residence {
class Residence {
var numberOfRooms = 1 var numberOfRooms = 1
} }
```
Residence有一个Int类型的属性numberOfRooms其默认值为1。Person具有一个可空的residence属性其类型为Residence `Residence`有一个`Int`类型的属性`numberOfRooms`其默认值为1。`Person`具有一个可空的`residence`属性,其类型为`Residence?`
如果创建一个新的Person实例因为它的residence属性是可空的john属性将初始化为nil 如果创建一个新的`Person`实例,因为它的`residence`属性是可空的,`john`属性将初始化为`nil`
let john = Person() ```swift
let john = Person()
```
如果使用叹号强制展开获得这个johnresidence属性中的numberOfRooms值会触发运行时错误因为这时没有可以展开的residence 如果使用叹号(!)强制展开获得这个`john``residence`属性中的`numberOfRooms`值,会触发运行时错误,因为这时没有可以展开的`residence`
let roomCount = john.residence!.numberOfRooms ```swift
// this triggers a runtime error let roomCount = john.residence!.numberOfRooms
// this triggers a runtime error
```
john.residence非空的时候上面的调用成功并且把roomCount设置为Int类型的房间数量。正如上面说到的当residence为空的时候上面这段代码会触发运行时错误。 `john.residence`非空的时候,上面的调用成功,并且把`roomCount`设置为`Int`类型的房间数量。正如上面说到的,当`residence`为空的时候上面这段代码会触发运行时错误。
可空链式调用提供了一种另一种访问numberOfRooms的方法使用问号来代替原来叹号的位置 可空链式调用提供了一种另一种访问`numberOfRooms`的方法,使用问号(?)来代替原来叹号(!)的位置:
if let roomCount = john.residence?.numberOfRooms { ```swift
print("John's residence has \(roomCount) room(s).") if let roomCount = john.residence?.numberOfRooms {
} else { print("John's residence has \(roomCount) room(s).")
print("Unable to retrieve the number of rooms.") } else {
} print("Unable to retrieve the number of rooms.")
// prints "Unable to retrieve the number of rooms." }
// prints "Unable to retrieve the number of rooms."
```
在residence后面添加问号之后Swift就会在residence不为空的情况下访问numberOfRooms。 `residence`后面添加问号之后Swift就会在`residence`不为空的情况下访问`numberOfRooms`
因为访问numberOfRooms有可能失败可空链式调用会返回Int?类型或称为“可空的Int”。如上例所示当residencenil的时候可空的Int将会为nil表明无法访问numberOfRooms。 因为访问`numberOfRooms`有可能失败,可空链式调用会返回`Int?`类型或称为“可空的Int”。如上例所示`residence``nil`的时候,可空的`Int`将会为`nil`,表明无法访问`numberOfRooms`
要注意的是即使numberOfRooms是不可空的Int时这一点也成立。只要是通过可空链式调用就意味着最后numberOfRooms返回一个Int而不是Int。 要注意的是,即使`numberOfRooms`是不可空的`Int`时,这一点也成立。只要是通过可空链式调用就意味着最后`numberOfRooms`返回一个`Int?`而不是`Int`
通过赋给john.residence一个Residence的实例变量 通过赋给`john.residence`一个`Residence`的实例变量:
john.residence = Residence() ```swift
这样john.residence不为nil了。现在就可以正常访问john.residence.numberOfRooms其值为默认的1类型为Int? john.residence = Residence()
```
if let roomCount = john.residence?.numberOfRooms { 这样`john.residence`不为`nil`了。现在就可以正常访问`john.residence.numberOfRooms`其值为默认的1类型为`Int?`
```swift
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s).") print("John's residence has \(roomCount) room(s).")
} else { } else {
print("Unable to retrieve the number of rooms.") print("Unable to retrieve the number of rooms.")
} }
// prints "John's residence has 1 room(s)." // prints "John's residence has 1 room(s)."
```
##为可空链式调用定义模型类 ##为可空链式调用定义模型类
通过使用可空链式调用可以调用多层属性,方法,和下标。这样可以通过各种模型向下访问各种子属性。并且判断能否访问子属性的属性,方法或下标。 通过使用可空链式调用可以调用多层属性,方法,和下标。这样可以通过各种模型向下访问各种子属性。并且判断能否访问子属性的属性,方法或下标。
下面这段代码定义了四个模型类这些例子包括多层可空链式调用。为了方便说明在PersonResidence的基础上增加了RoomAddress以及相关的属性方法以及下标。 下面这段代码定义了四个模型类,这些例子包括多层可空链式调用。为了方便说明,在`Person``Residence`的基础上增加了`Room``Address`,以及相关的属性,方法以及下标。
Person类定义基本保持不变 Person类定义基本保持不变
class Person { ```swift
var residence: Residence? class Person {
} var residence: Residence?
Residence类比之前复杂些增加了一个Room类型的空数组room }
```
class Residence { `Residence`类比之前复杂些,增加了一个`Room`类型的空数组`room`
var rooms = [Room]()
var numberOfRooms: Int {
return rooms.count
}
subscript(i: Int) -> Room {
get {
return rooms[i]
}
set {
rooms[i] = newValue
}
}
func printNumberOfRooms() {
print("The number of rooms is \(numberOfRooms)")
}
var address: Address?
}
现在Residence有了一个存储Room类型的数组numberOfRooms属性需要计算而不是作为单纯的变量。计算后的numberOfRooms返回rooms数组的count属性值。现在的Residence还提供访问rooms数组的快捷方式 通过可读写的下标来访问指定位置的数组元素。此外还提供printNumberOfRooms方法这个方法的作用就是输出这个房子中房间的数量。最后Residence定义了一个可空属性address其类型为Address?。Address类的定义在下面会说明。 ```swift
class Residence {
var rooms = [Room]()
var numberOfRooms: Int {
return rooms.count
}
subscript(i: Int) -> Room {
get {
return rooms[i]
}
set {
rooms[i] = newValue
}
}
func printNumberOfRooms() {
print("The number of rooms is \(numberOfRooms)")
}
var address: Address?
}
```
类Room是一个简单类只包含一个属性name以及一个初始化函数 现在`Residence`有了一个存储`Room`类型的数组,`numberOfRooms`属性需要计算,而不是作为单纯的变量。计算后的`numberOfRooms`返回`rooms`数组的`count`属性值。现在的`Residence`还提供访问`rooms`数组的快捷方式, 通过可读写的下标来访问指定位置的数组元素。此外,还提供`printNumberOfRooms`方法,这个方法的作用就是输出这个房子中房间的数量。最后,`Residence`定义了一个可空属性`address`,其类型为`Address?``Address`类的定义在下面会说明。
class Room { `Room`是一个简单类,只包含一个属性`name`,以及一个初始化函数:
let name: String
init(name: String) { self.name = name }
}
最后一个类是Address这个类有三个String?类型的可空属性。buildingName以及buildingNumber属性表示建筑的名称和号码用来表示某个特定的建筑。第三个属性表示建筑所在街道的名称
class Address { ```swift
var buildingName: String? class Room {
var buildingNumber: String? let name: String
var street: String? init(name: String) { self.name = name }
func buildingIdentifier() -> String? { }
if buildingName != nil { ```
return buildingName
} else if buildingNumber != nil { 最后一个类是`Address`,这个类有三个`String?`类型的可空属性。`buildingName`以及`buildingNumber`属性表示建筑的名称和号码,用来表示某个特定的建筑。第三个属性表示建筑所在街道的名称:
return buildingNumber
} else { ```swift
return nil class Address {
} var buildingName: String?
} var buildingNumber: String?
} var street: String?
类Address提供buildingIdentifier()方法返回值为String?。 如果buildingName不为空则返回buildingName 如果buildingNumber不为空则返回buildingNumber。如果这两个属性都为空则返回nil。 func buildingIdentifier() -> String? {
if buildingName != nil {
return buildingName
} else if buildingNumber != nil {
return buildingNumber
} else {
return nil
}
}
}
```
`Address`提供`buildingIdentifier()`方法,返回值为`String?`。 如果`buildingName`不为空则返回`buildingName` 如果`buildingNumber`不为空则返回`buildingNumber`。如果这两个属性都为空则返回`nil`
##通过可空链式调用访问属性 ##通过可空链式调用访问属性
正如[可空链式调用作为强制展开的另一个方案]中所述,可以通过可空链式调用访问属性的可空值,并且判断访问是否成功。 正如[使用可空链式调用强制展开](#optional_chaining_as_an_alternative_to_forced_unwrapping)中所述,可以通过可空链式调用访问属性的可空值,并且判断访问是否成功。
下面的代码创建了一个Person实例然后访问numberOfRooms属性 下面的代码创建了一个`Person`实例,然后访问`numberOfRooms`属性:
let john = Person() ```swift
if let roomCount = john.residence?.numberOfRooms { let john = Person()
print("John's residence has \(roomCount) room(s).") if let roomCount = john.residence?.numberOfRooms {
} else { print("John's residence has \(roomCount) room(s).")
print("Unable to retrieve the number of rooms.") } else {
} print("Unable to retrieve the number of rooms.")
// prints "Unable to retrieve the number of rooms." }
因为john.residence为nil所以毫无疑问这个可空链式调用失败。 // prints "Unable to retrieve the number of rooms."
```
因为`john.residence``nil`,所以毫无疑问这个可空链式调用失败。
通过可空链式调用来设定属性值: 通过可空链式调用来设定属性值:
let someAddress = Address() ```swift
someAddress.buildingNumber = "29" let someAddress = Address()
someAddress.street = "Acacia Road" someAddress.buildingNumber = "29"
john.residence?.address = someAddress someAddress.street = "Acacia Road"
在这个例子中通过john.residence来设定address属性也是不行的因为john.residence为nil。 john.residence?.address = someAddress
```
在这个例子中,通过`john.residence`来设定`address`属性也是不行的,因为`john.residence``nil`
##通过可空链式调用来调用方法 ##通过可空链式调用来调用方法
可以通过可空链式调用来调用方法,并判断是否调用成功,即使这个方法没有返回值。 可以通过可空链式调用来调用方法,并判断是否调用成功,即使这个方法没有返回值。
Residence中得printNumberOfRooms()方法输出当前的numberOfRooms值 `Residence`中的`printNumberOfRooms()`方法输出当前的`numberOfRooms`值:
func printNumberOfRooms() { ```swift
print("The number of rooms is \(numberOfRooms)") func printNumberOfRooms() {
} print("The number of rooms is \(numberOfRooms)")
这个方法没有返回值。但是没有返回值的方法隐式返回Void类型如[无返回值函数](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID163)中所述。这意味着没有返回值的方法也会返回()或者空的元组。 }
```
如果在可空值上通过可空链式调用来调用这个方法这个方法的返回类型为Void?而不是Void因为通过可空链式调用得到的返回值都是可空的。这样我们就可以使用if语句来判断能否成功调用printNumberOfRooms()方法即使方法本身没有定义返回值。通过返回值是否为nil可以判断调用是否成功 这个方法没有返回值。但是没有返回值的方法隐式返回`Void`类型,如[无返回值函数](./06_Functions.html#functions_without_return_values)中所述。这意味着没有返回值的方法也会返回()或者空的元组。
if john.residence?.printNumberOfRooms() != nil { 如果在可空值上通过可空链式调用来调用这个方法,这个方法的返回类型为`Void?`,而不是`Void`,因为通过可空链式调用得到的返回值都是可空的。这样我们就可以使用`if`语句来判断能否成功调用`printNumberOfRooms()`方法,即使方法本身没有定义返回值。通过返回值是否为`nil`可以判断调用是否成功:
print("It was possible to print the number of rooms.")
} else {
print("It was not possible to print the number of rooms.")
}
// prints "It was not possible to print the number of rooms."
同样的可以判断通过可空链式调用来给属性赋值是否成功。在上面的例子中我们尝试给john.residence中的address属性赋值即使residence为nil。通过可空链式调用给属性赋值会返回Void?通过判断返回值是否为nil可以知道赋值是否成功
if (john.residence?.address = someAddress) != nil { ```swift
if john.residence?.printNumberOfRooms() != nil {
print("It was possible to print the number of rooms.")
} else {
print("It was not possible to print the number of rooms.")
}
// prints "It was not possible to print the number of rooms."
```
同样的,可以判断通过可空链式调用来给属性赋值是否成功。在上面的例子中,我们尝试给`john.residence`中的`address`属性赋值,即使`residence``nil`。通过可空链式调用给属性赋值会返回`Void?`,通过判断返回值是否为`nil`可以知道赋值是否成功:
```swift
if (john.residence?.address = someAddress) != nil {
print("It was possible to set the address.") print("It was possible to set the address.")
} else { } else {
print("It was not possible to set the address.") print("It was not possible to set the address.")
} }
// prints "It was not possible to set the address." // prints "It was not possible to set the address."
```
##通过可空链式调用来访问下标 ##通过可空链式调用来访问下标
通过可空链式调用,我们可以用下标来对可空值进行读取或写入,并且判断下标调用是否成功。 通过可空链式调用,我们可以用下标来对可空值进行读取或写入,并且判断下标调用是否成功。
@ -177,44 +223,57 @@ Residence中得printNumberOfRooms()方法输出当前的numberOfRooms值
注意: 注意:
当通过可空链式调用访问可空值的下标的时候,应该将问号放在下标方括号的前面而不是后面。可空链式调用的问号一般直接跟在可空表达式的后面。 当通过可空链式调用访问可空值的下标的时候,应该将问号放在下标方括号的前面而不是后面。可空链式调用的问号一般直接跟在可空表达式的后面。
下面这个例子用下标访问john.residencerooms数组中第一个房间的名称因为john.residencenil所以下标调用毫无疑问失败了 下面这个例子用下标访问`john.residence``rooms`数组中第一个房间的名称,因为`john.residence``nil`,所以下标调用毫无疑问失败了:
if let firstRoomName = john.residence?[0].name { ```swift
print("The first room name is \(firstRoomName).") if let firstRoomName = john.residence?[0].name {
} else { print("The first room name is \(firstRoomName).")
print("Unable to retrieve the first room name.") } else {
} print("Unable to retrieve the first room name.")
// prints "Unable to retrieve the first room name." }
在这个例子中问号直接放在john.residence的后面并且在方括号的前面因为john.residence是可空值。 // prints "Unable to retrieve the first room name."
```
在这个例子中,问号直接放在`john.residence`的后面,并且在方括号的前面,因为`john.residence`是可空值。
类似的,可以通过下标,用可空链式调用来赋值: 类似的,可以通过下标,用可空链式调用来赋值:
```swift
john.residence?[0] = Room(name: "Bathroom") john.residence?[0] = Room(name: "Bathroom")
```
这次赋值同样会失败,因为`residence`目前是`nil` 这次赋值同样会失败,因为`residence`目前是`nil`
如果你创建一个Residence实例添加一些Room实例并赋值给john.residence那就可以通过可选链和下标来访问数组中的元素 如果你创建一个`Residence`实例,添加一些`Room`实例并赋值给`john.residence`,那就可以通过可选链和下标来访问数组中的元素:
let johnsHouse = Residence() ```swift
johnsHouse.rooms.append(Room(name: "Living Room")) let johnsHouse = Residence()
johnsHouse.rooms.append(Room(name: "Kitchen")) johnsHouse.rooms.append(Room(name: "Living Room"))
john.residence = johnsHouse johnsHouse.rooms.append(Room(name: "Kitchen"))
if let firstRoomName = john.residence?[0].name { john.residence = johnsHouse
if let firstRoomName = john.residence?[0].name {
print("The first room name is \(firstRoomName).") print("The first room name is \(firstRoomName).")
} else { } else {
print("Unable to retrieve the first room name.") print("Unable to retrieve the first room name.")
} }
// prints "The first room name is Living Room." // prints "The first room name is Living Room."
```
##访问可空类型的下标: ##访问可空类型的下标:
如果下标返回可空类型值比如Swift中Dictionarykey下标。可以在下标的闭合括号后面放一个问号来链接下标的可空返回值 如果下标返回可空类型值比如Swift中`Dictionary``key`下标。可以在下标的闭合括号后面放一个问号来链接下标的可空返回值:
var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]] ```swift
testScores["Dave"]?[0] = 91 var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]
testScores["Bev"]?[0]++ testScores["Dave"]?[0] = 91
testScores["Brian"]?[0] = 72 testScores["Bev"]?[0]++
// the "Dave" array is now [91, 82, 84] and the "Bev" array is now [80, 94, 81] testScores["Brian"]?[0] = 72
上面的例子中定义了一个testScores数组包含了两个键值对 把String类型的key映射到一个整形数组。这个例子用可空链式调用把“Dave”数组中第一个元素设为91把”Bev”数组的第一个元素+1然后尝试把”Brian”数组中的第一个元素设为72。前两个调用是成功的因为这两个key存在。但是key“Brian”在字典中不存在所以第三个调用失败。 // the "Dave" array is now [91, 82, 84] and the "Bev" array is now [80, 94, 81]
```
上面的例子中定义了一个`testScores`数组,包含了两个键值对, 把`String`类型的`key`映射到一个整形数组。这个例子用可空链式调用把“Dave”数组中第一个元素设为91把”Bev”数组的第一个元素+1然后尝试把”Brian”数组中的第一个元素设为72。前两个调用是成功的因为这两个`key`存在。但是key“Brian”在字典中不存在所以第三个调用失败。
##多层链接 ##多层链接
可以通过多个链接多个可空链式调用来向下访问属性,方法以及下标。但是多层可空链式调用不会添加返回值的可空性。 可以通过多个链接多个可空链式调用来向下访问属性,方法以及下标。但是多层可空链式调用不会添加返回值的可空性。
@ -226,58 +285,68 @@ john.residence?[0] = Room(name: "Bathroom")
因此: 因此:
+ 通过可空链式调用访问一个Int值将会返回Int,不过进行了多少次可空链式调用。 + 通过可空链式调用访问一个`Int`值,将会返回`Int?`,不过进行了多少次可空链式调用。
+ 类似的通过可空链式调用访问Int?值,并不会变得更加可空。 + 类似的,通过可空链式调用访问`Int?`值,并不会变得更加可空。
下面的例子访问john中的residence中的address中的street属性。这里使用了两层可空链式调用residence以及address这两个都是可空值。 下面的例子访问`john`中的`residence`中的`address`中的`street`属性。这里使用了两层可空链式调用,`residence`以及`address`,这两个都是可空值。
if let johnsStreet = john.residence?.address?.street { ```swift
print("John's street name is \(johnsStreet).") if let johnsStreet = john.residence?.address?.street {
} else { print("John's street name is \(johnsStreet).")
print("Unable to retrieve the address.") } else {
} print("Unable to retrieve the address.")
// prints "Unable to retrieve the address." }
// prints "Unable to retrieve the address."
```
john.residence包含Residence实例但是john.residence.addressnil。因此不能访问john.residence?.address?.street。 `john.residence`包含`Residence`实例,但是`john.residence.address``nil`。因此,不能访问`john.residence?.address?.street`
需要注意的是上面的例子中street的属性为String?john.residence?.address?.street的返回值也依然是String?,即使已经进行了两次可空的链式调用。 需要注意的是,上面的例子中,`street`的属性为`String?``john.residence?.address?.street`的返回值也依然是`String?`,即使已经进行了两次可空的链式调用。
如果把john.residence.address指向一个实例并且为address中的street属性赋值我们就能过通过可空链式调用来访问street属性。 如果把`john.residence.address`指向一个实例,并且为`address`中的`street`属性赋值,我们就能过通过可空链式调用来访问`street`属性。
let johnsAddress = Address() ```swift
johnsAddress.buildingName = "The Larches" let johnsAddress = Address()
johnsAddress.street = "Laurel Street" johnsAddress.buildingName = "The Larches"
john.residence?.address = johnsAddress johnsAddress.street = "Laurel Street"
john.residence?.address = johnsAddress
if let johnsStreet = john.residence?.address?.street {
print("John's street name is \(johnsStreet).") if let johnsStreet = john.residence?.address?.street {
} else { print("John's street name is \(johnsStreet).")
print("Unable to retrieve the address.") } else {
} print("Unable to retrieve the address.")
// prints "John's street name is Laurel Street." }
在上面的例子中因为john.residence是一个可用的Residence实例所以对john.residence的address属性赋值成功。 // prints "John's street name is Laurel Street."
```
在上面的例子中,因为`john.residence`是一个可用的`Residence`实例,所以对`john.residence``address`属性赋值成功。
##对返回可空值的函数进行链接 ##对返回可空值的函数进行链接
上面的例子说明了如何通过可空链式调用来获取可空属性值。我们还可以通过可空链式调用来调用返回可空值的方法,并且可以继续对可空值进行链接。 上面的例子说明了如何通过可空链式调用来获取可空属性值。我们还可以通过可空链式调用来调用返回可空值的方法,并且可以继续对可空值进行链接。
在下面的例子中通过可空链式调用来调用AddressbuildingIdentifier()方法。这个方法返回String?类型。正如上面所说通过可空链式调用的方法的最终返回值还是String? 在下面的例子中,通过可空链式调用来调用`Address``buildingIdentifier()`方法。这个方法返回`String?`类型。正如上面所说,通过可空链式调用的方法的最终返回值还是`String?`
if let buildingIdentifier = john.residence?.address?.buildingIdentifier() { ```swift
print("John's building identifier is \(buildingIdentifier).") if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
} print("John's building identifier is \(buildingIdentifier).")
// prints "John's building identifier is The Larches." }
// prints "John's building identifier is The Larches."
```
如果要进一步对方法的返回值进行可空链式调用在方法buildingIdentifier()的圆括号后面加上问号: 如果要进一步对方法的返回值进行可空链式调用,在方法`buildingIdentifier()`的圆括号后面加上问号:
if let beginsWithThe = ```swift
if let beginsWithThe =
john.residence?.address?.buildingIdentifier()?.hasPrefix("The") { john.residence?.address?.buildingIdentifier()?.hasPrefix("The") {
if beginsWithThe { if beginsWithThe {
print("John's building identifier begins with \"The\".") print("John's building identifier begins with \"The\".")
} else { } else {
print("John's building identifier does not begin with \"The\".") print("John's building identifier does not begin with \"The\".")
} }
} }
// prints "John's building identifier begins with "The"." // prints "John's building identifier begins with "The"."
```
> >
注意: 注意:
在上面的例子中在在方法的圆括号后面加上问号是因为buildingIdentifier()的返回值是可空值,而不是方法本身是可空的。 在上面的例子中在,在方法的圆括号后面加上问号是因为`buildingIdentifier()`的返回值是可空值,而不是方法本身是可空的。

View File

@ -1,3 +1,6 @@
> 2.0
> 翻译+校对:[lyojo](https://github.com/lyojo)
# 错误处理 # 错误处理
----------------- -----------------
错误处理是响应错误以及从错误中返回的过程。swift提供第一类错误支持包括在运行时抛出捕获传送和控制可回收错误。 错误处理是响应错误以及从错误中返回的过程。swift提供第一类错误支持包括在运行时抛出捕获传送和控制可回收错误。
@ -7,136 +10,167 @@
举个例子,考虑到一个从磁盘上的一个文件读取以及处理数据的任务,有几种情况可能会导致这个任务失败,包括指定路径的文件不存在,文件不具有可读属性,或者文件没有被编码成合适的格式。区分这些错误可以让程序解决并且修复这些错误,并且,如果可能的话,把这些错误报告给用户。 举个例子,考虑到一个从磁盘上的一个文件读取以及处理数据的任务,有几种情况可能会导致这个任务失败,包括指定路径的文件不存在,文件不具有可读属性,或者文件没有被编码成合适的格式。区分这些错误可以让程序解决并且修复这些错误,并且,如果可能的话,把这些错误报告给用户。
> >
NOTE 注意
Swift中的错误处理涉及到错误处理样式这会用到Cocoa中的NSError和Objective-C。更多信息请参见[Error Handling](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html#//apple_ref/doc/uid/TP40014216-CH7-ID10)中的[Using Swift with Cocoa and Objective-C](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)。 Swift中的错误处理涉及到错误处理样式这会用到Cocoa中的NSError和Objective-C。更多信息请参见[Using Swift with Cocoa and Objective-C](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)中的[错误处理](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html#//apple_ref/doc/uid/TP40014216-CH7-ID10)。
###错误的表示: ###错误的表示:
在Swift中错误用符合ErrorType协议的值表示。 在Swift中错误用符合`ErrorType`协议的值表示。
Swift枚举特别适合把一系列相关的错误组合在一起同时可以把一些相关的值和错误关联在一起。因此编译器会为实现ErrorType协议的Swift枚举类型自动实现相应合成。 Swift枚举特别适合把一系列相关的错误组合在一起同时可以把一些相关的值和错误关联在一起。因此编译器会为实现`ErrorType`协议的Swift枚举类型自动实现相应合成。
比如说,你可以这样表示操作自动贩卖机会出现的错误: 比如说,你可以这样表示操作自动贩卖机会出现的错误:
enum VendingMachineError: ErrorType { ```swift
enum VendingMachineError: ErrorType {
case InvalidSelection case InvalidSelection
case InsufficientFunds(required: Double) case InsufficientFunds(required: Double)
case OutOfStock case OutOfStock
} }
```
在这种情况下,自动贩卖机可能会因为以下原因失败: 在这种情况下,自动贩卖机可能会因为以下原因失败:
请求的物品不存在用InvalidSelection表示。 请求的物品不存在,用`InvalidSelection`表示。
请求的物品的价格高于已投入金额用InsufficientFunds表示。相关的双精度值表示还需要多少钱来完成此次交易。 请求的物品的价格高于已投入金额,用`InsufficientFunds`表示。相关的双精度值表示还需要多少钱来完成此次交易。
请求的物品已经卖完了用OutOfStock表示。 请求的物品已经卖完了,用`OutOfStock`表示。
<a name="throwing_errors"></a>
错误抛出 错误抛出
通过在函数或方法声明的参数后面加上throws关键字表明这个函数或方法可以抛出错误。如果指定一个返回值可以把throws关键字放在返回箭头(->)的前面。除非明确地指出,一个函数,方法或者就闭包不能抛出错误。 通过在函数或方法声明的参数后面加上`throws`关键字,表明这个函数或方法可以抛出错误。如果指定一个返回值,可以把`throws`关键字放在返回箭头(->)的前面。除非明确地指出,一个函数,方法或者就闭包不能抛出错误。
func canThrowErrors() throws -> String ```swift
func cannotThrowErrors() -> String func canThrowErrors() throws -> String
在抛出函数体的任意一个地方可以通过throw语句抛出错误。在下面的例子中如果请求的物品不存在或者卖完了或者超出投入金额vend(itemNamed:)函数会抛出一个错误: func cannotThrowErrors() -> String
```
struct Item { 在抛出函数体的任意一个地方,可以通过`throw`语句抛出错误。在下面的例子中,如果请求的物品不存在,或者卖完了,或者超出投入金额,`vend(itemNamed:)`函数会抛出一个错误:
```swift
struct Item {
var price: Double var price: Double
var count: Int var count: Int
} }
var inventory = [
var inventory = [
"Candy Bar": Item(price: 1.25, count: 7), "Candy Bar": Item(price: 1.25, count: 7),
"Chips": Item(price: 1.00, count: 4), "Chips": Item(price: 1.00, count: 4),
"Pretzels": Item(price: 0.75, count: 11) "Pretzels": Item(price: 0.75, count: 11)
] ]
var amountDeposited = 1.00 var amountDeposited = 1.00
func vend(itemNamed name: String) throws {
func vend(itemNamed name: String) throws {
guard var item = inventory[name] else { guard var item = inventory[name] else {
throw VendingMachineError.InvalidSelection throw VendingMachineError.InvalidSelection
} }
guard item.count > 0 else { guard item.count > 0 else {
throw VendingMachineError.OutOfStock throw VendingMachineError.OutOfStock
} }
if amountDeposited >= item.price { if amountDeposited >= item.price {
// Dispense the snack // Dispense the snack
amountDeposited -= item.price amountDeposited -= item.price
--item.count --item.count
inventory[name] = item inventory[name] = item
} else { } else {
let amountRequired = item.price - amountDeposited let amountRequired = item.price - amountDeposited
throw VendingMachineError.InsufficientFunds(required: amountRequired) throw VendingMachineError.InsufficientFunds(required: amountRequired)
}
} }
首先guard语句用来把绑定item常量和count变量到在库存中对应的值。如果物品不在库存中将会抛出InvalidSelection错误。然后物品是否可获取有物品的剩余数量决定。如果count小于等于0将会抛出OutOfStock错误。最后把请求物品的价格和已经投入的金额进行比较如果如果投入的金额大于物品的价格将会从投入的金额从减去物品的价格然后库存中该物品的数量减1然后返回请求的物品。否则将会计算还需要多少钱然后把这个值作为InsufficientFunds错误的关联值。因为throw语句会马上改变程序流程当所有的购买条件物品存在库存足够以及投入金额足够都满足的时候物品才会出售。 }
```
当调用一个抛出函数的时候在调用前面加上try。这个关键字表明函数可以抛出错误而且在try后面代码将不会执行 首先,`guard`语句用来把绑定`item`常量和`count`变量到在库存中对应的值。如果物品不在库存中,将会抛出`InvalidSelection`错误。然后,物品是否可获取有物品的剩余数量决定。如果`count`小于等于0将会抛出`OutOfStock`错误。最后把请求物品的价格和已经投入的金额进行比较如果如果投入的金额大于物品的价格将会从投入的金额从减去物品的价格然后库存中该物品的数量减1然后返回请求的物品。否则将会计算还需要多少钱然后把这个值作为`InsufficientFunds`错误的关联值。因为`throw`语句会马上改变程序流程,当所有的购买条件(物品存在,库存足够以及投入金额足够)都满足的时候,物品才会出售
let favoriteSnacks = [ 当调用一个抛出函数的时候,在调用前面加上`try`。这个关键字表明函数可以抛出错误,而且在`try`后面代码将不会执行。
```swift
let favoriteSnacks = [
"Alice": "Chips", "Alice": "Chips",
"Bob": "Licorice", "Bob": "Licorice",
"Eve": "Pretzels", "Eve": "Pretzels",
] ]
func buyFavoriteSnack(person: String) throws { func buyFavoriteSnack(person: String) throws {
let snackName = favoriteSnacks[person] ?? "Candy Bar" let snackName = favoriteSnacks[person] ?? "Candy Bar"
try vend(itemNamed: snackName) try vend(itemNamed: snackName)
} }
buyFavoriteSnack(_:) 函数查找某个人的最喜欢的零食然后尝试买给他。如果这个人在列表中没有喜欢的零食就会购买Candy Bar。这个函数会调用vend函数vend函数可能会抛出错误所以在vend前面加上了try关键字。因为buyFavoriteSnack函数也是一个抛出函数所以vend函数抛出的任何错误都会向上传递到buyFavoriteSnack被调用的地方。 ```
`buyFavoriteSnack(_:)` 函数查找某个人的最喜欢的零食,然后尝试买给他。如果这个人在列表中没有喜欢的零食,就会购买`Candy Bar`。这个函数会调用`vend`函数,`vend`函数可能会抛出错误,所以在`vend`前面加上了`try`关键字。因为`buyFavoriteSnack`函数也是一个抛出函数,所以`vend`函数抛出的任何错误都会向上传递到`buyFavoriteSnack`被调用的地方。
###捕捉和处理错误 ###捕捉和处理错误
使用do-catch语句来就捕获和处理错误 使用do-catch语句来就捕获和处理错误
do { ```swift
do {
try function that throws
statements
} catch pattern {
statements
} try function that throws
如果一个错误被抛出了这个错误会被传递到外部域直到被一个catch分句处理。一个catch分句包含一个catch关键字跟着一个pattern来匹配错误和相应的执行语句。
类似switch语句编译器会检查catch分句是否能够处理全部错误。如果能够处理所有错误情况就认为这个错误被完全处理。否者包含这个抛出函数的所在域就要处理这个错误或者包含这个抛出函数的函数也用throws声明。为了保证错误被处理用一个带pattern的catch分句来匹配所有错误。如果一个catch分句没有指定样式这个分句会匹配并且绑定任何错误到一个本地error常量。更多关于pattern的信息参见[Patterns](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Patterns.html#//apple_ref/doc/uid/TP40014097-CH36-ID419)。 statements
} catch pattern {
do { statements
}
```
如果一个错误被抛出了,这个错误会被传递到外部域,直到被一个`catch`分句处理。一个`catch`分句包含一个`catch`关键字,跟着一个`pattern`来匹配错误和相应的执行语句。
类似`switch`语句,编译器会检查`catch`分句是否能够处理全部错误。如果能够处理所有错误情况,就认为这个错误被完全处理。否者,包含这个抛出函数的所在域就要处理这个错误,或者包含这个抛出函数的函数也用`throws`声明。为了保证错误被处理,用一个带`pattern``catch`分句来匹配所有错误。如果一个`catch`分句没有指定样式,这个分句会匹配并且绑定任何错误到一个本地`error`常量。更多关于`pattern`的信息,参见[模式](../chapter3/07_Patterns.html)。
```swift
do {
try vend(itemNamed: "Candy Bar") try vend(itemNamed: "Candy Bar")
// Enjoy delicious snack // Enjoy delicious snack
} catch VendingMachineError.InvalidSelectio { } catch VendingMachineError.InvalidSelectio {
print("Invalid Selection") print("Invalid Selection")
} catch VendingMachineError.OutOfStock { } catch VendingMachineError.OutOfStock {
print("Out of Stock.") print("Out of Stock.")
} catch VendingMachineError.InsufficientFunds(let amountRequired) { } catch VendingMachineError.InsufficientFunds(let amountRequired) {
print("Insufficient funds. Please insert an additional $\(amountRequired).") print("Insufficient funds. Please insert an additional $\(amountRequired).")
} }
```
在上面的例子中vend(itemNamed:) 函数在try表达式中被调用因为这个函数会抛出错误。如果抛出了错误程序执行流程马上转到catch分句在catch分句中确定错误传递是否继续传送。如果没有抛出错误将会执行在do语句中剩余的语句。 在上面的例子中,`vend(itemNamed:)` 函数在`try`表达式中被调用,因为这个函数会抛出错误。如果抛出了错误,程序执行流程马上转到`catch`分句,在`catch`分句中确定错误传递是否继续传送。如果没有抛出错误,将会执行在`do`语句中剩余的语句。
###禁止错误传送 > 注意Swift中的错误处理和其他语言中的异常处理很像使用了`try`、`catch`和`throw`关键字。但是和这些语言——包括Objective-C——不同的是Swift不会展开调用堆栈那会带来很大的性能损耗。因此在Swift中`throw`语句的性能可以做到几乎和`return`语句一样。
在运行时有几种情况抛出函数事实上是不会抛出错误的。在这几种情况下你可以用forced-try表达式来调用抛出函数或方法即使用try!来代替try。
通过try!来调用抛出函数或方法禁止错误传送,并且把调用包装在运行时断言,这样就不会抛出错误。如果错误真的抛出了,会触发运行时错误。 ###禁止错误传
在运行时,有几种情况抛出函数事实上是不会抛出错误的。在这几种情况下,你可以用`forced-try`表达式来调用抛出函数或方法,即使用`try!`来代替`try`
func willOnlyThrowIfTrue(value: Bool) throws { 通过`try!`来调用抛出函数或方法禁止了错误传送,并且把调用包装在运行时断言,这样就不会抛出错误。如果错误真的抛出了,会触发运行时错误。
```swift
func willOnlyThrowIfTrue(value: Bool) throws {
if value { throw someError } if value { throw someError }
} }
do {
do {
try willOnlyThrowIfTrue(false) try willOnlyThrowIfTrue(false)
} catch { } catch {
// Handle Error // Handle Error
} }
try! willOnlyThrowIfTrue(false)
try! willOnlyThrowIfTrue(false)
```
###收尾操作 ###收尾操作
使用defer语句来在执行一系列的语句。这样不管有没有错误发生都可以执行一些必要的收尾操作。包括关闭打开的文件描述符以及释放所有手动分配的内存。 使用defer语句来在执行一系列的语句。这样不管有没有错误发生都可以执行一些必要的收尾操作。包括关闭打开的文件描述符以及释放所有手动分配的内存。
defer语句把执行推迟到退出当前域的时候。defer语句包括defer关键字以及后面要执行的语句。被推迟的语句可能不包含任何将执行流程转移到外部的代码比如break或者return语句或者通过抛出一个错误。被推迟的操作的执行的顺序和他们定义的顺序相反也就是说在第一个defer语句中的代码在第二个defer语句中的代码之后执行。 `defer`语句把执行推迟到退出当前域的时候。`defer`语句包括`defer`关键字以及后面要执行的语句。被推迟的语句可能不包含任何将执行流程转移到外部的代码,比如`break`或者`return`语句,或者通过抛出一个错误。被推迟的操作的执行的顺序和他们定义的顺序相反,也就是说,在第一个`defer`语句中的代码在第二个`defer`语句中的代码之后执行。
func processFile(filename: String) throws { ```swift
func processFile(filename: String) throws {
if exists(filename) { if exists(filename) {
let file = open(filename) let file = open(filename)
defer { defer {
close(file) close(file)
}
while let line = try file.readline() {
/* Work with the file. */
}
// close(file) is called here, at the end of the scope.
} }
} while let line = try file.readline() {
上面这个例子使用了defer语句来保证open有对应的close。这个调用不管是否有抛出都会执行。 // Work with the file.
}
// close(file) is called here, at the end of the scope.
}
}
```
上面这个例子使用了`defer`语句来保证`open`有对应的`close`。这个调用不管是否有抛出都会执行。

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[Lin-H](https://github.com/Lin-H) > 翻译:[Lin-H](https://github.com/Lin-H)
> 校对:[shinyzhu](https://github.com/shinyzhu) > 校对:[shinyzhu](https://github.com/shinyzhu)
> 2.0
> 翻译+校对:[SergioChan](https://github.com/SergioChan)
# 嵌套类型 # 嵌套类型
----------------- -----------------
@ -72,7 +76,7 @@ struct BlackjackCard {
`BlackjackCard`结构体自身有两个属性—`rank``suit`,也同样定义了一个计算属性`description``description`属性用`rank``suit`的中内容来构建对这张扑克牌名字和数值的描述,并用可选类型`second`来检查是否存在第二个值,若存在,则在原有的描述中增加对第二数值的描述。 `BlackjackCard`结构体自身有两个属性—`rank``suit`,也同样定义了一个计算属性`description``description`属性用`rank``suit`的中内容来构建对这张扑克牌名字和数值的描述,并用可选类型`second`来检查是否存在第二个值,若存在,则在原有的描述中增加对第二数值的描述。
因为`BlackjackCard`是一个没有自定义构造函数的结构体,在[Memberwise Initializers for Structure Types](https://github.com/CocoaChina-editors/Welcome-to-Swift/blob/master/The%20Swift%20Programming%20Language/02Language%20Guide/14Initialization.md)中知道结构体有默认的成员构造函数,所以你可以用默认的`initializer`去初始化新的常量`theAceOfSpades`: 因为`BlackjackCard`是一个没有自定义构造函数的结构体,在[结构体的逐一成员构造器](./14_Initialization.html#memberwise_initializers_for_structure_types)中知道结构体有默认的成员构造函数,所以你可以用默认的`initializer`去初始化新的常量`theAceOfSpades`:
```swift ```swift
let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades) let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades)

View File

@ -1,5 +1,9 @@
> 1.0
> 翻译:[xiehurricane](https://github.com/xiehurricane) > 翻译:[xiehurricane](https://github.com/xiehurricane)
> 校对:[happyming](https://github.com/happyming) [yangsiy](https://github.com/yangsiy) > 校对:[happyming](https://github.com/happyming)
> 2.0
> 翻译+校对:[yangsiy](https://github.com/yangsiy)
# 类型转换Type Casting # 类型转换Type Casting
----------------- -----------------
@ -16,7 +20,7 @@ _类型转换_可以判断实例的类型也可以将实例看做是其父类
类型转换在 Swift 中使用 `is``as` 操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。 类型转换在 Swift 中使用 `is``as` 操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。
你也可以用它来检查一个类是否实现了某个协议,就像在 [Checking for Protocol Conformance](Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_363)部分讲述的一样。 你也可以用它来检查一个类是否实现了某个协议,就像在 [检验协议的一致性](./22_Protocols.html#checking_for_protocol_conformance)部分讲述的一样。
<a name="defining_a_class_hierarchy_for_type_casting"></a> <a name="defining_a_class_hierarchy_for_type_casting"></a>
## 定义一个类层次作为例子 ## 定义一个类层次作为例子
@ -155,6 +159,7 @@ Swift为不确定类型提供了两种特殊类型别名
> 注意: > 注意:
> 只有当你明确的需要它的行为和功能时才使用`Any`和`AnyObject`。在你的代码里使用你期望的明确的类型总是更好的。 > 只有当你明确的需要它的行为和功能时才使用`Any`和`AnyObject`。在你的代码里使用你期望的明确的类型总是更好的。
<a name="anyobject"></a>
### `AnyObject`类型 ### `AnyObject`类型
当在工作中使用 Cocoa APIs我们一般会接收一个`[AnyObject]`类型的数组,或者说“一个任何对象类型的数组”。这是因为 Objective-C 没有明确的类型化数组。但是,你常常可以从 API 提供的信息中清晰地确定数组中对象的类型。 当在工作中使用 Cocoa APIs我们一般会接收一个`[AnyObject]`类型的数组,或者说“一个任何对象类型的数组”。这是因为 Objective-C 没有明确的类型化数组。但是,你常常可以从 API 提供的信息中清晰地确定数组中对象的类型。

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[lyuka](https://github.com/lyuka) > 翻译:[lyuka](https://github.com/lyuka)
> 校对:[Hawstein](https://github.com/Hawstein) > 校对:[Hawstein](https://github.com/Hawstein)
> 2.0
> 翻译+校对:[shanksyang](https://github.com/shanksyang)
#扩展Extensions #扩展Extensions
---- ----
@ -25,7 +29,7 @@ Swift 中的扩展可以:
- 使一个已有类型符合某个协议 - 使一个已有类型符合某个协议
TODO TODO
在 Swift 中,你甚至可以对一个协议(Procotol)进行扩展,提供协议需要的实现,或者添加额外的功能能够对合适的类型带来额外的好处。你可以从[协议扩展](#)获取更多的细节。 在 Swift 中,你甚至可以对一个协议(Procotol)进行扩展,提供协议需要的实现,或者添加额外的功能能够对合适的类型带来额外的好处。你可以从[协议扩展](./Protocols.html#protocol_extensions)获取更多的细节。
>注意: >注意:
扩展可以对一个类型添加新的功能,但是不能重写已有的功能。 扩展可以对一个类型添加新的功能,但是不能重写已有的功能。
@ -48,7 +52,7 @@ extension SomeType: SomeProtocol, AnotherProctocol {
} }
``` ```
按照这种方式添加的协议遵循者protocol conformance被称之为[在扩展中添加协议遵循者](21_Protocols.html#adding_protocol_conformance_with_an_extension) 按照这种方式添加的协议遵循者protocol conformance被称之为[在扩展中添加协议遵循者](./21_Protocols.html#adding_protocol_conformance_with_an_extension)
>注意: >注意:
如果你定义了一个扩展向一个已有类型添加新功能,那么这个新功能对该类型的所有已有实例中都是可用的,即使它们是在你的这个扩展的前面定义的。 如果你定义了一个扩展向一个已有类型添加新功能,那么这个新功能对该类型的所有已有实例中都是可用的,即使它们是在你的这个扩展的前面定义的。
@ -101,7 +105,7 @@ print("A marathon is \(aMarathon) meters long")
> 注意: > 注意:
如果你使用扩展向一个值类型添加一个构造器在该值类型已经向所有的存储属性提供默认值而且没有定义任何定制构造器custom initializers你可以在值类型的扩展构造器中调用默认构造器(default initializers)和逐一成员构造器(memberwise initializers)。 如果你使用扩展向一个值类型添加一个构造器在该值类型已经向所有的存储属性提供默认值而且没有定义任何定制构造器custom initializers你可以在值类型的扩展构造器中调用默认构造器(default initializers)和逐一成员构造器(memberwise initializers)。
> >
正如在[值类型的构造器代理](14_Initialization.html#initializer_delegation_for_value_types)中描述的,如果你已经把构造器写成值类型原始实现的一部分,上述规则不再适用。 正如在[值类型的构造器代理](./14_Initialization.html#initializer_delegation_for_value_types)中描述的,如果你已经把构造器写成值类型原始实现的一部分,上述规则不再适用。
下面的例子定义了一个用于描述几何矩形的定制结构体`Rect`。这个例子同时定义了两个辅助结构体`Size``Point`,它们都把`0.0`作为所有属性的默认值: 下面的例子定义了一个用于描述几何矩形的定制结构体`Rect`。这个例子同时定义了两个辅助结构体`Size``Point`,它们都把`0.0`作为所有属性的默认值:
@ -117,7 +121,7 @@ struct Rect {
var size = Size() var size = Size()
} }
``` ```
因为结构体`Rect`提供了其所有属性的默认值,所以正如[默认构造器](14_Initialization.html#default_initializers)中描述的,它可以自动接受一个默认构造器和一个逐一成员构造器。这些构造器可以用于构造新的`Rect`实例: 因为结构体`Rect`提供了其所有属性的默认值,所以正如[默认构造器](./14_Initialization.html#default_initializers)中描述的,它可以自动接受一个默认构造器和一个逐一成员构造器。这些构造器可以用于构造新的`Rect`实例:
```swift ```swift
let defaultRect = Rect() let defaultRect = Rect()

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[geek5nan](https://github.com/geek5nan) > 翻译:[geek5nan](https://github.com/geek5nan)
> 校对:[dabing1022](https://github.com/dabing1022) > 校对:[dabing1022](https://github.com/dabing1022)
> 2.0
> 翻译+校对:[futantan](https://github.com/futantan)
# 协议 # 协议
----------------- -----------------
@ -170,7 +174,7 @@ print("And another one: \(generator.random())")
<a name="mutating_method_requirements"></a> <a name="mutating_method_requirements"></a>
## 对Mutating方法的规定 ## 对Mutating方法的规定
有时需要在方法中改变它的实例。例如,值类型(结构体,枚举)的实例方法中,将`mutating`关键字作为函数的前缀,写在`func`之前,表示可以在该方法中修改它所属的实例及其实例属性的值。这一过程在[Modifyting Value Types from Within Instance Methods](TODO)章节中有详细描述。 有时需要在方法中改变它的实例。例如,值类型(结构体,枚举)的实例方法中,将`mutating`关键字作为函数的前缀,写在`func`之前,表示可以在该方法中修改它所属的实例及其实例属性的值。这一过程在[在实例方法中修改值类型](./11_Methods.html#modifying_value_types_from_within_instance_methods)章节中有详细描述。
如果你在协议中定义了一个方法旨在改变遵循该协议的实例,那么在协议定义时需要在方法前加`mutating`关键字。这使得结构和枚举遵循协议并满足此方法要求。 如果你在协议中定义了一个方法旨在改变遵循该协议的实例,那么在协议定义时需要在方法前加`mutating`关键字。这使得结构和枚举遵循协议并满足此方法要求。
@ -234,12 +238,10 @@ class SomeClass: SomeProtocol {
使用`required`修饰符可以保证:所有的遵循该协议的子类,同样能为构造器规定提供一个显式的实现或继承实现。 使用`required`修饰符可以保证:所有的遵循该协议的子类,同样能为构造器规定提供一个显式的实现或继承实现。
<!--TODO 参考链接--> 关于`required`构造器的更多内容,请参考[必要构造器](./14_Initialization.html#required_initializers)。
关于`required`构造器的更多内容,请参考<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_454">`Required`构造器 </a>
<!--TODO 参考链接-->
>注意 >注意
>如果类已经被标记为`final`,那么不需要在协议构造器的实现中使用`required`修饰符。因为final类不能有子类。关于`final`修饰符的更多内容,请参见<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_339">防止重写</a> >如果类已经被标记为`final`,那么不需要在协议构造器的实现中使用`required`修饰符。因为final类不能有子类。关于`final`修饰符的更多内容,请参见[防止重写](./13_Inheritance.html#preventing_overrides)。
如果一个子类重写了父类的指定构造器,并且该构造器遵循了某个协议的规定,那么该构造器的实现需要被同时标示`required``override`修饰符 如果一个子类重写了父类的指定构造器,并且该构造器遵循了某个协议的规定,那么该构造器的实现需要被同时标示`required``override`修饰符
@ -266,7 +268,7 @@ class SomeSubClass: SomeSuperClass, SomeProtocol {
### 可失败构造器的规定 ### 可失败构造器的规定
可以通过给协议`Protocols`中添加可失败构造器来使遵循该协议的类型必须实现该可失败构造器。 可以通过给协议`Protocols`中添加[可失败构造器](./14_Initialization.html#failable_initializers)来使遵循该协议的类型必须实现该可失败构造器。
如果在协议中定义一个可失败构造器,则在遵顼该协议的类型中必须添加同名同参数的可失败构造器或非可失败构造器。如果在协议中定义一个非可失败构造器,则在遵循该协议的类型中必须添加同名同参数的非可失败构造器或隐式解析类型的可失败构造器(`init!`)。 如果在协议中定义一个可失败构造器,则在遵顼该协议的类型中必须添加同名同参数的可失败构造器或非可失败构造器。如果在协议中定义一个非可失败构造器,则在遵循该协议的类型中必须添加同名同参数的非可失败构造器或隐式解析类型的可失败构造器(`init!`)。
@ -346,7 +348,7 @@ protocol DiceGameDelegate {
`DiceGame`协议可以在任意含有骰子的游戏中实现。`DiceGameDelegate`协议可以用来追踪`DiceGame`的游戏过程 `DiceGame`协议可以在任意含有骰子的游戏中实现。`DiceGameDelegate`协议可以用来追踪`DiceGame`的游戏过程
如下所示,`SnakesAndLadders`是`Snakes and Ladders`(译者注:[Control Flow](2)章节有该游戏的详细介绍)游戏的新版本。新版本使用`Dice`作为骰子,并且实现了`DiceGame``DiceGameDelegate`协议,后者用来记录游戏的过程: 如下所示,`SnakesAndLadders`是`Snakes and Ladders`([Control Flow](./05_Control_Flow.html)章节有该游戏的详细介绍)游戏的新版本。新版本使用`Dice`作为骰子,并且实现了`DiceGame``DiceGameDelegate`协议,后者用来记录游戏的过程:
```swift ```swift
class SnakesAndLadders: DiceGame { class SnakesAndLadders: DiceGame {
@ -438,7 +440,7 @@ game.play()
<a name="adding_protocol_conformance_with_an_extension"></a> <a name="adding_protocol_conformance_with_an_extension"></a>
## 在扩展中添加协议成员 ## 在扩展中添加协议成员
即便无法修改源代码,依然可以通过扩展(Extension)来扩充已存在类型(*译者注: 类,结构体,枚举等*)。扩展可以为已存在的类型添加属性,方法,下标脚本,协议等成员。详情请在[扩展](4)章节中查看。 即便无法修改源代码,依然可以通过扩展(Extension)来扩充已存在类型(*译者注: 类,结构体,枚举等*)。扩展可以为已存在的类型添加属性,方法,下标脚本,协议等成员。详情请在[扩展](./21_Extensions.html)章节中查看。
> 注意 > 注意
> 通过扩展为已存在的类型遵循协议时,该类型的所有实例也会随之添加协议中的方法 > 通过扩展为已存在的类型遵循协议时,该类型的所有实例也会随之添加协议中的方法
@ -602,7 +604,7 @@ protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
<!--TODO 链接--> <!--TODO 链接-->
>注意 >注意
>当协议想要定义的行为,要求(或假设)它的遵循类型必须是引用语义而非值语义时,应该采用类专属协议。关于引用语义,值语义的更多内容,请查看<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_145">结构体和枚举是值类型</a><a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_146">类是引用类型</a> >当协议想要定义的行为,要求(或假设)它的遵循类型必须是引用语义而非值语义时,应该采用类专属协议。关于引用语义,值语义的更多内容,请查看[结构体和枚举是值类型](./09_Classes_and_Structures.html#structures_and_enumerations_are_value_types)和[类是引用类型](./09_Classes_and_Structures.html#classes_are_reference_types)。
<a name="protocol_composition"></a> <a name="protocol_composition"></a>
@ -644,7 +646,7 @@ wishHappyBirthday(birthdayPerson)
## 检验协议的一致性 ## 检验协议的一致性
<!--TODO 链接--> <!--TODO 链接-->
你可以使用`is``as`操作符来检查是否遵循某一协议或强制转化为某一类型。检查和转化的语法和之前相同(*详情查看[Typy Casting章节](5)*): 你可以使用`is``as`操作符来检查是否遵循某一协议或强制转化为某一类型。检查和转化的语法和之前相同(*详情查看[类型转换](./20_Type_Casting.html)*):
* `is`操作符用来检查实例是否`遵循`了某个`协议` * `is`操作符用来检查实例是否`遵循`了某个`协议`
* `as?`返回一个可选值,当实例`遵循`协议时,返回该协议类型;否则返回`nil` * `as?`返回一个可选值,当实例`遵循`协议时,返回该协议类型;否则返回`nil`
@ -721,7 +723,7 @@ for object in objects {
协议可以含有可选成员,其`遵循者`可以选择是否实现这些成员。在协议中使用`optional`关键字作为前缀来定义可选成员。 协议可以含有可选成员,其`遵循者`可以选择是否实现这些成员。在协议中使用`optional`关键字作为前缀来定义可选成员。
<!--TODO 链接--> <!--TODO 链接-->
可选协议在调用时使用`可选链`,因为协议的遵循者可能没有实现可选内容,详细内容在[Optional Chaning](7)章节中查看。 可选协议在调用时使用`可选链`,因为协议的遵循者可能没有实现可选内容,详细内容在[可空链式调用](./17_Optional_Chaining.html)章节中查看。
`someOptionalMethod?(someArgument)`这样,你可以在可选方法名称后加上`?`来检查该方法是否被实现。可选方法和可选属性都会返回一个`可选值(optional value)`,当其不可访问时,`?`之后语句不会执行,并整体返回`nil` `someOptionalMethod?(someArgument)`这样,你可以在可选方法名称后加上`?`来检查该方法是否被实现。可选方法和可选属性都会返回一个`可选值(optional value)`,当其不可访问时,`?`之后语句不会执行,并整体返回`nil`
@ -876,7 +878,7 @@ extension PrettyTextRepresentable {
### 为协议扩展添加限制条件 ### 为协议扩展添加限制条件
在扩展协议的时候,可以指定一些限制,只有满足这些限制的协议遵循者,才能获得协议扩展提供的属性和方法。这些限制写在协议名之后,使用`where`关键字来描述限制情况。([Where](TODO))。: 在扩展协议的时候,可以指定一些限制,只有满足这些限制的协议遵循者,才能获得协议扩展提供的属性和方法。这些限制写在协议名之后,使用`where`关键字来描述限制情况。([Where](./23_Generics.html#where_clauses))。:
例如,你可以扩展`CollectionType`协议,但是只适用于元素遵循`TextRepresentable`的情况: 例如,你可以扩展`CollectionType`协议,但是只适用于元素遵循`TextRepresentable`的情况:

View File

@ -1,7 +1,10 @@
> 1.0
> 翻译:[takalard](https://github.com/takalard) [SergioChan](https://github.com/SergioChan) > 翻译:[takalard](https://github.com/takalard)
> 校对:[lifedim](https://github.com/lifedim) > 校对:[lifedim](https://github.com/lifedim)
> 2.0
> 翻译+校对: [SergioChan](https://github.com/SergioChan)
# 泛型 # 泛型
------ ------
@ -35,7 +38,7 @@ func swapTwoInts(inout a: Int, inout _ b: Int) {
} }
``` ```
这个函数使用写入读出in-out参数来交换`a``b`的值,请参考[写入读出参数](../chapter2/06_Functions.html)。 这个函数使用写入读出in-out参数来交换`a``b`的值,请参考[输入输出参数](./06_Functions.html#in_out_parameters)。
`swapTwoInts(_:_:)`函数可以交换`b`的原始值到`a`也可以交换a的原始值到`b`,你可以调用这个函数交换两个`Int`变量值: `swapTwoInts(_:_:)`函数可以交换`b`的原始值到`a`也可以交换a的原始值到`b`,你可以调用这个函数交换两个`Int`变量值:
@ -260,7 +263,7 @@ if let topItem = stackOfStrings.topItem {
`swapTwoValues(_:_:)`函数和`Stack`类型可以作用于任何类型,不过,有的时候对使用在泛型函数和泛型类型上的类型强制约束为某种特定类型是非常有用的。类型约束指定了一个必须继承自指定类的类型参数,或者遵循一个特定的协议或协议构成。 `swapTwoValues(_:_:)`函数和`Stack`类型可以作用于任何类型,不过,有的时候对使用在泛型函数和泛型类型上的类型强制约束为某种特定类型是非常有用的。类型约束指定了一个必须继承自指定类的类型参数,或者遵循一个特定的协议或协议构成。
例如Swift 的`Dictionary`类型对作用于其键的类型做了些限制。在[字典](../chapter2/04_Collection_Types.html)的描述中,字典的键类型必须是*可哈希*,也就是说,必须有一种方法可以使其被唯一的表示。`Dictionary`之所以需要其键是可哈希是为了以便于其检查其是否已经包含某个特定键的值。如无此需求,`Dictionary`既不会告诉是否插入或者替换了某个特定键的值,也不能查找到已经存储在字典里面的给定键值。 例如Swift 的`Dictionary`类型对作用于其键的类型做了些限制。在[字典](./04_Collection_Types.html#dictionaries)的描述中,字典的键类型必须是*可哈希*,也就是说,必须有一种方法可以使其被唯一的表示。`Dictionary`之所以需要其键是可哈希是为了以便于其检查其是否已经包含某个特定键的值。如无此需求,`Dictionary`既不会告诉是否插入或者替换了某个特定键的值,也不能查找到已经存储在字典里面的给定键值。
这个需求强制加上一个类型约束作用于`Dictionary`的键上,当然其键类型必须遵循`Hashable`协议Swift 标准库中定义的一个特定协议)。所有的 Swift 基本类型(如`String``Int` `Double``Bool`)默认都是可哈希。 这个需求强制加上一个类型约束作用于`Dictionary`的键上,当然其键类型必须遵循`Hashable`协议Swift 标准库中定义的一个特定协议)。所有的 Swift 基本类型(如`String``Int` `Double``Bool`)默认都是可哈希。
@ -443,9 +446,9 @@ struct Stack<T>: Container {
### 扩展一个存在的类型为一指定关联类型 ### 扩展一个存在的类型为一指定关联类型
在[使用扩展添加协议兼容性](../chapter2/21_Protocols.html)中有描述扩展一个存在的类型添加遵循一个协议。这个类型包含一个关联类型的协议。 在[扩展添加协议成员](./21_Protocols.html#adding_protocol_conformance_with_an_extension)中有描述扩展一个存在的类型添加遵循一个协议。这个类型包含一个关联类型的协议。
Swift的`Array`已经提供`append(_:)`方法,一个`count`属性和通过下标来查找一个自己的元素。这三个功能都达到`Container`协议的要求。也就意味着你可以扩展`Array`去遵循`Container`协议,只要通过简单声明`Array`适用于该协议而已。如何实践这样一个空扩展,在[使用扩展来声明协议的采纳](../chapter2/21_Protocols.html)中有描述这样一个实现一个空扩展的行为: Swift的`Array`已经提供`append(_:)`方法,一个`count`属性和通过下标来查找一个自己的元素。这三个功能都达到`Container`协议的要求。也就意味着你可以扩展`Array`去遵循`Container`协议,只要通过简单声明`Array`适用于该协议而已。如何实践这样一个空扩展,在[通过扩展补充协议声明](./21_Protocols.html#declaring_protocol_adoption_with_an_extension)中有描述这样一个实现一个空扩展的行为:
```swift ```swift
extension Array: Container {} extension Array: Container {}

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[JaceFu](http://www.devtalking.com/) > 翻译:[JaceFu](http://www.devtalking.com/)
> 校对:[ChildhoodAndy](http://childhood.logdown.com) > 校对:[ChildhoodAndy](http://childhood.logdown.com)
> 2.0
> 翻译+校对:[mmoaay](https://github.com/mmoaay)
# 访问控制 # 访问控制
------------------ ------------------
@ -288,13 +292,13 @@ public struct TrackedString {
<a name="initializers"></a> <a name="initializers"></a>
## 初始化 ## 初始化
我们可以给自定义的初始化方法申明访问级别,但是要不高于它所属类的访问级别。但[必要构造器](TODO)例外,它的访问级别必须和所属类的访问级别相同。 我们可以给自定义的初始化方法申明访问级别,但是要不高于它所属类的访问级别。但[必要构造器](./14_Initialization.html#required_initializers)例外,它的访问级别必须和所属类的访问级别相同。
如同函数或方法参数,初始化方法参数的访问级别也不能低于初始化方法的访问级别。 如同函数或方法参数,初始化方法参数的访问级别也不能低于初始化方法的访问级别。
<a name="default_initializers"></a> <a name="default_initializers"></a>
### 默认初始化方法 ### 默认初始化方法
Swift为结构体、类都提供了一个默认的无参初始化方法用于给它们的所有属性提供赋值操作但不会给出具体值。默认初始化方法可以参阅[Default Initializers](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_336)。默认初始化方法的访问级别与所属类型的访问级别相同。 Swift为结构体、类都提供了一个默认的无参初始化方法用于给它们的所有属性提供赋值操作但不会给出具体值。默认初始化方法可以参阅[默认构造器](./14_Initialization.html#default_initializers)。默认初始化方法的访问级别与所属类型的访问级别相同。
> 注意:如果一个类型被申明为`public`级别,那么默认的初始化方法的访问级别为`internal`。如果你想让无参的初始化方法在其他模块中可以被使用,那么你必须提供一个具有`public`访问级别的无参初始化方法。 > 注意:如果一个类型被申明为`public`级别,那么默认的初始化方法的访问级别为`internal`。如果你想让无参的初始化方法在其他模块中可以被使用,那么你必须提供一个具有`public`访问级别的无参初始化方法。

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[xielingwang](https://github.com/xielingwang) > 翻译:[xielingwang](https://github.com/xielingwang)
> 校对:[numbbbbb](https://github.com/numbbbbb) > 校对:[numbbbbb](https://github.com/numbbbbb)
> 2.0
> 翻译+校对:[buginux](https://github.com/buginux)
# 高级运算符 # 高级运算符
----------------- -----------------
@ -12,7 +16,7 @@
- [运算符函数(Operator Functions)](#operator_functions) - [运算符函数(Operator Functions)](#operator_functions)
- [自定义运算符](#custom_operators) - [自定义运算符](#custom_operators)
除了在之前介绍过的[基本运算符](02_Basic_Operators.html)Swift 中还有许多可以对数值进行复杂操作的高级运算符。这些高级运算符包含了在 C 和 Objective-C 中已经被大家所熟知的位运算符和移位运算符。 除了在之前介绍过的[基本运算符](./02_Basic_Operators.html)Swift 中还有许多可以对数值进行复杂操作的高级运算符。这些高级运算符包含了在 C 和 Objective-C 中已经被大家所熟知的位运算符和移位运算符。
与C语言中的算术运算符不同Swift 中的算术运算符默认是不会溢出的。所有溢出行为都会被捕获并报告为错误。如果想让系统允许溢出行为,可以选择使用 Swift 中另一套默认支持溢出的运算符,比如溢出加法运算符(`&+`)。所有的这些溢出运算符都是以 `&` 开头的。 与C语言中的算术运算符不同Swift 中的算术运算符默认是不会溢出的。所有溢出行为都会被捕获并报告为错误。如果想让系统允许溢出行为,可以选择使用 Swift 中另一套默认支持溢出的运算符,比如溢出加法运算符(`&+`)。所有的这些溢出运算符都是以 `&` 开头的。
@ -393,7 +397,8 @@ let afterIncrement = ++toIncrement
> 注意: > 注意:
> 不能对默认的赋值运算符(`=`)进行重载。只有组合赋值符可以被重载。同样地,也无法对三目条件运算符 `a ? b : c` 进行重载。 > 不能对默认的赋值运算符(`=`)进行重载。只有组合赋值符可以被重载。同样地,也无法对三目条件运算符 `a ? b : c` 进行重载。
### 等价运算符 <a name="equivalence_operators"></a>
### 等价操作符
自定义的类和结构体没有对等价操作符(`equivalence operators`)进行默认实现,等价操作符通常被称为“相等”操作符(`==`)与“不等”操作符(`!=`)。对于自定义类型Swift 无法判断其是否“相等”,因为“相等”的含义取决于这些自定义类型在你的代码中所扮演的角色。 自定义的类和结构体没有对等价操作符(`equivalence operators`)进行默认实现,等价操作符通常被称为“相等”操作符(`==`)与“不等”操作符(`!=`)。对于自定义类型Swift 无法判断其是否“相等”,因为“相等”的含义取决于这些自定义类型在你的代码中所扮演的角色。
@ -421,6 +426,7 @@ if twoThree == anotherTwoThree {
// prints "These two vectors are equivalent." // prints "These two vectors are equivalent."
``` ```
<a name="custom_operators"></a>
### 自定义运算符 ### 自定义运算符
除了实现标准运算符,在 Swift 当中还可以声明和实现自定义运算符(`custom operators`)。可以用来自定义运算符的字符列表请参考[操作符](../chapter3/02_Lexical_Structure.html#operators) 除了实现标准运算符,在 Swift 当中还可以声明和实现自定义运算符(`custom operators`)。可以用来自定义运算符的字符列表请参考[操作符](../chapter3/02_Lexical_Structure.html#operators)

View File

@ -1,5 +1,9 @@
> 1.0
> 翻译:[dabing1022](https://github.com/dabing1022) > 翻译:[dabing1022](https://github.com/dabing1022)
> 校对:[numbbbbb](https://github.com/numbbbbb), [KYawn](https://github.com/KYawn) > 校对:[numbbbbb](https://github.com/numbbbbb)
> 2.0
> 翻译+校对:[KYawn](https://github.com/KYawn)
# 关于语言附注 # 关于语言附注

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[superkam](https://github.com/superkam) > 翻译:[superkam](https://github.com/superkam)
> 校对:[numbbbbb](https://github.com/numbbbbb) > 校对:[numbbbbb](https://github.com/numbbbbb)
> 2.0
> 翻译+校对:[buginux]([KYawn](https://github.com/buginux)
# 词法结构 # 词法结构
----------------- -----------------
@ -202,14 +206,14 @@ true // 布尔型字面量
let x = 3; "1 2 \(x)" let x = 3; "1 2 \(x)"
``` ```
字符串字面量的默认推导类型为 `String`。组成字符串的字符默认推导类型为 `Character`。更多有关 `String``Character` 的信息请参照 [字符串和字符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-XID_368)。 字符串字面量的默认推导类型为 `String`。组成字符串的字符默认推导类型为 `Character`。更多有关 `String``Character` 的信息请参照 [字符串和字符](../chapter2/03_Strings_and_Characters.html)。
> 字符型字面量语法 > 字符型字面量语法
> *字符串字面量* → **"** [*引用文本*](#quoted_text)<sub>可选</sub> **"** > *字符串字面量* → **"** [*引用文本*](#quoted_text)<sub>可选</sub> **"**
<a id="quoted_text"></a> <a id="quoted_text"></a>
> *引用文本* → [*引用文本条目*](#quoted_text_item) [*引用文本*](#quoted_text) <sub>可选</sub> > *引用文本* → [*引用文本条目*](#quoted_text_item) [*引用文本*](#quoted_text) <sub>可选</sub>
> *引用文本条目* → [*转义字符*](#escaped_character) > *引用文本条目* → [*转义字符*](#escaped_character)
> *引用文本条目* → **\(** [*表达式*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID383) **)** > *引用文本条目* → **\(** [*表达式*](./04_Expressions.html) **)**
> *引用文本条目* → **除了"­, \­, U+000A, 或者 U+000D的所有Unicode的字符** > *引用文本条目* → **除了"­, \­, U+000A, 或者 U+000D的所有Unicode的字符**
> *转义字符* → **\0** | **\\** | **\t** | **\n** | **\r** | **\"** | **\'** > *转义字符* → **\0** | **\\** | **\t** | **\n** | **\r** | **\"** | **\'**
> *转义字符* → **\u {** [*unicode标量数字*](#unicode_scalar_digits) **}** > *转义字符* → **\u {** [*unicode标量数字*](#unicode_scalar_digits) **}**
@ -218,7 +222,7 @@ let x = 3; "1 2 \(x)"
<a id="operators"></a> <a id="operators"></a>
## 运算符 ## 运算符
Swift 标准库定义了许多可供使用的运算符,其中大部分在 [基础运算符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-XID_70) 和 [高级运算符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_28) 中进行了阐述。这一小节将描述哪些字符能用于自定义运算符。 Swift 标准库定义了许多可供使用的运算符,其中大部分在 [基础运算符](../chapter2/02_Basic_Operators.html) 和 [高级运算符](../chapter2/25_Advanced_Operators.html) 中进行了阐述。这一小节将描述哪些字符能用于自定义运算符。
自定义运算符可以由以下其中之一的 ASCII 字符 `/``=``-``+``!``*``%``<``>``&``|``^``?` 以及 `~`, 或者后面语法中规定的任一个 Unicode 字符开始。在第一个字符之后,允许使用组合型 Unicode 字符。也可以使用两个或者多个的点号来自定义运算符(比如, `....`)。虽然可以自定义包含问号`?`的运算符,但是这个运算符不能只包含单独的一个问号。 自定义运算符可以由以下其中之一的 ASCII 字符 `/``=``-``+``!``*``%``<``>``&``|``^``?` 以及 `~`, 或者后面语法中规定的任一个 Unicode 字符开始。在第一个字符之后,允许使用组合型 Unicode 字符。也可以使用两个或者多个的点号来自定义运算符(比如, `....`)。虽然可以自定义包含问号`?`的运算符,但是这个运算符不能只包含单独的一个问号。
@ -238,7 +242,7 @@ Swift 标准库定义了许多可供使用的运算符,其中大部分在 [基
在某些特定的构造中 ,以 `<``>` 开头的运算符会被分离成两个或多个标记,剩余部分以同样的方式会被再次分离。因此,在 `Dictionary<String, Array<Int>>` 中没有必要添加空白来消除闭合字符 `>` 的歧义。在这个例子中, 闭合字符 `>` 不会被视为单独的标记,因而不会被误解析为 `>>` 运算符的一部分。 在某些特定的构造中 ,以 `<``>` 开头的运算符会被分离成两个或多个标记,剩余部分以同样的方式会被再次分离。因此,在 `Dictionary<String, Array<Int>>` 中没有必要添加空白来消除闭合字符 `>` 的歧义。在这个例子中, 闭合字符 `>` 不会被视为单独的标记,因而不会被误解析为 `>>` 运算符的一部分。
要学习如何自定义运算符,请参考 [自定义操作符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_48) 和 [运算符声明](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-XID_644)。要学习如何重载运算符,请参考 [运算符方法](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-XID_43)。 要学习如何自定义运算符,请参考 [自定义操作符](../chapter2/25_Advanced_Operators.html#custom_operators) 和 [运算符声明](./05_Declarations.html#operator_declaration)。要学习如何重载运算符,请参考 [运算符方法](../chapter2/25_Advanced_Operators.html#operator_functions)。
> 运算符语法语法 > 运算符语法语法
> *运算符* → [*头部运算符*](#operator_head) [*运算符字符组*](#operator_characters)<sub>可选</sub> > *运算符* → [*头部运算符*](#operator_head) [*运算符字符组*](#operator_characters)<sub>可选</sub>

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[lyuka](https://github.com/lyuka) > 翻译:[lyuka](https://github.com/lyuka)
> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai) > 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[EudeMorgen](https://github.com/EudeMorgen)
# 类型Types # 类型Types
----------------- -----------------
@ -27,7 +31,7 @@ Swift 语言存在两种类型:命名型类型和复合型类型。命名型
本节讨论 Swift 语言本身定义的类型,并描述 Swift 中的类型推断行为。 本节讨论 Swift 语言本身定义的类型,并描述 Swift 中的类型推断行为。
> 类型语法 > 类型语法
> *类型* → [*数组类型*](#array_type) | [*字典类型*](..\chapter3\03_Types.html#dictionary_type) | [*函数类型*](..\chapter3\03_Types.html#function_type) | [*类型标识*](..\chapter3\03_Types.html#type_identifier) | [*元组类型*](..\chapter3\03_Types.html#tuple_type) | [*可选类型*](..\chapter3\03_Types.html#optional_type) | [*隐式解析可选类型*](..\chapter3\03_Types.html#implicitly_unwrapped_optional_type) | [*协议合成类型*](..\chapter3\03_Types.html#protocol_composition_type) | [*元型类型*](..\chapter3\03_Types.html#metatype_type) > *类型* → [*数组类型*](#array_type) | [*字典类型*](../chapter3/03_Types.html#dictionary_type) | [*函数类型*](../chapter3/03_Types.html#function_type) | [*类型标识*](../chapter3/03_Types.html#type_identifier) | [*元组类型*](../chapter3/03_Types.html#tuple_type) | [*可选类型*](../chapter3/03_Types.html#optional_type) | [*隐式解析可选类型*](../chapter3/03_Types.html#implicitly_unwrapped_optional_type) | [*协议合成类型*](../chapter3/03_Types.html#protocol_composition_type) | [*元型类型*](../chapter3/03_Types.html#metatype_type)
<a name="type_annotation"></a> <a name="type_annotation"></a>
##类型注解 ##类型注解
@ -43,7 +47,7 @@ func someFunction(a: Int){ /* ... */ }
类型注解可以在类型之前包含一个类型特性type attributes的可选列表。 类型注解可以在类型之前包含一个类型特性type attributes的可选列表。
> 类型注解语法 > 类型注解语法
> *类型注解* → **:** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type) > *类型注解* → **:** [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*类型*](../chapter3/03_Types.html#type)
<a name="type_identifier"></a> <a name="type_identifier"></a>
##类型标识符 ##类型标识符
@ -66,7 +70,7 @@ var someValue: ExampleModule.MyType
``` ```
> 类型标识语法 > 类型标识语法
> *类型标识* → [*类型名称*](..\chapter3\03_Types.html#type_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ | [*类型名称*](..\chapter3\03_Types.html#type_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ **.** [*类型标识*](..\chapter3\03_Types.html#type_identifier) > *类型标识* → [*类型名称*](../chapter3/03_Types.html#type_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ | [*类型名称*](../chapter3/03_Types.html#type_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ **.** [*类型标识*](../chapter3/03_Types.html#type_identifier)
> *类名* → [*标识符*](LexicalStructure.html#identifier) > *类名* → [*标识符*](LexicalStructure.html#identifier)
<a name="tuple_type"></a> <a name="tuple_type"></a>
@ -79,10 +83,10 @@ var someValue: ExampleModule.MyType
`void`是空元组类型`()`的别名。如果括号内只有一个元素,那么该类型就是括号内元素的类型。比如,`(Int)`的类型是`Int`而不是`(Int)`。所以,只有当元组类型包含的元素个数在两个及以上时才可以命名元组元素。 `void`是空元组类型`()`的别名。如果括号内只有一个元素,那么该类型就是括号内元素的类型。比如,`(Int)`的类型是`Int`而不是`(Int)`。所以,只有当元组类型包含的元素个数在两个及以上时才可以命名元组元素。
> 元组类型语法 > 元组类型语法
> *元组类型* → **(** [*元组类型主体*](..\chapter3\03_Types.html#tuple_type_body) _可选_ **)** > *元组类型* → **(** [*元组类型主体*](../chapter3/03_Types.html#tuple_type_body) _可选_ **)**
> *元组类型主体* → [*元组类型的元素列表*](..\chapter3\03_Types.html#tuple_type_element_list) **...** _可选_ > *元组类型主体* → [*元组类型的元素列表*](../chapter3/03_Types.html#tuple_type_element_list) **...** _可选_
> *元组类型的元素列表* → [*元组类型的元素*](..\chapter3\03_Types.html#tuple_type_element) | [*元组类型的元素*](..\chapter3\03_Types.html#tuple_type_element) **,** [*元组类型的元素列表*](..\chapter3\03_Types.html#tuple_type_element_list) > *元组类型的元素列表* → [*元组类型的元素*](../chapter3/03_Types.html#tuple_type_element) | [*元组类型的元素*](../chapter3/03_Types.html#tuple_type_element) **,** [*元组类型的元素列表*](../chapter3/03_Types.html#tuple_type_element_list)
> *元组类型的元素* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **inout** _可选_ [*类型*](..\chapter3\03_Types.html#type) | **inout** _可选_ [*元素名*](..\chapter3\03_Types.html#element_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation) > *元组类型的元素* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ **inout** _可选_ [*类型*](../chapter3/03_Types.html#type) | **inout** _可选_ [*元素名*](../chapter3/03_Types.html#element_name) [*类型注解*](../chapter3/03_Types.html#type_annotation)
> *元素名* → [*标识符*](LexicalStructure.html#identifier) > *元素名* → [*标识符*](LexicalStructure.html#identifier)
<a name="function_type"></a> <a name="function_type"></a>
@ -115,8 +119,8 @@ simpleAssert(testNumber % 2 == 0, "testNumber isn't an even number.")
函数类型若要抛出错误就必须使用`throws`关键字来标记,若要重抛错误则必须使用`rethrows`关键字来标记。`throws`关键字是函数类型的一部分不抛出函数nonthrowing function是抛出函数throwing function函数的一个子类型。因此在使用抛出函数的地方也可以使用不抛出函数。对于柯里化函数`throws`关键字只应用于最里层的函数。抛出和重抛函数rethrowing function的相关描述见章节抛出函数与方法和重抛函数与方法。 函数类型若要抛出错误就必须使用`throws`关键字来标记,若要重抛错误则必须使用`rethrows`关键字来标记。`throws`关键字是函数类型的一部分不抛出函数nonthrowing function是抛出函数throwing function函数的一个子类型。因此在使用抛出函数的地方也可以使用不抛出函数。对于柯里化函数`throws`关键字只应用于最里层的函数。抛出和重抛函数rethrowing function的相关描述见章节抛出函数与方法和重抛函数与方法。
> 函数类型语法 > 函数类型语法
> *函数类型* → [*类型*](..\chapter3\03_Types.html#type) _抛出_ _可选_ **->** [*类型*](..\chapter3\03_Types.html#type) > *函数类型* → [*类型*](../chapter3/03_Types.html#type) _抛出_ _可选_ **->** [*类型*](../chapter3/03_Types.html#type)
> *函数类型* → [*类型*](..\chapter3\03_Types.html#type)_重抛_ **->** [*类型*](..\chapter3\03_Types.html#type) > *函数类型* → [*类型*](../chapter3/03_Types.html#type)_重抛_ **->** [*类型*](../chapter3/03_Types.html#type)
<a name="array_type"></a> <a name="array_type"></a>
##数组类型 ##数组类型
@ -140,7 +144,7 @@ var array3D: [[[Int]]] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
关于Swift标准库中`Array`类型的细节讨论见章节Arrays。 关于Swift标准库中`Array`类型的细节讨论见章节Arrays。
> 数组类型语法 > 数组类型语法
> *数组类型* → [*类型*](..\chapter3\03_Types.html#type) > *数组类型* → [*类型*](../chapter3/03_Types.html#type)
<a name="dictionary_type"></a> <a name="dictionary_type"></a>
##字典类型 ##字典类型
@ -161,7 +165,7 @@ let someDictionary: Dictionary<String, Int> = ["Alex": 31, "Paul": 39]
关于Swift标准库中`Dictionary`类型的更多细节可查看章节Dictionaries。 关于Swift标准库中`Dictionary`类型的更多细节可查看章节Dictionaries。
> 字典类型语法 > 字典类型语法
> *字典类型* → **[**[*类型*](..\chapter3\03_Types.html#type) **:** [*类型*](..\chapter3\03_Types.html#type) **]** > *字典类型* → **[**[*类型*](../chapter3/03_Types.html#type) **:** [*类型*](../chapter3/03_Types.html#type) **]**
<a name="optional_type"></a> <a name="optional_type"></a>
##可选类型 ##可选类型
@ -191,7 +195,7 @@ optionalInteger! // 42
更多细节以及更多如何使用可选类型的例子见章节Optionals。 更多细节以及更多如何使用可选类型的例子见章节Optionals。
> 可选类型语法 > 可选类型语法
> *可选类型* → [*类型*](..\chapter3\03_Types.html#type) **?** > *可选类型* → [*类型*](../chapter3/03_Types.html#type) **?**
<a name="implicitly_unwrapped_optional_type"></a> <a name="implicitly_unwrapped_optional_type"></a>
##隐式解析可选类型 ##隐式解析可选类型
@ -215,7 +219,7 @@ var implicitlyUnwrappedString: ImplicitlyUnwrappedOptional<String>
关于隐式解析可选的更多细节见章节Implicitly Unwrapped Optionals。 关于隐式解析可选的更多细节见章节Implicitly Unwrapped Optionals。
> 隐式解析可选类型(Implicitly Unwrapped Optional Type)语法 > 隐式解析可选类型(Implicitly Unwrapped Optional Type)语法
> *隐式解析可选类型* → [*类型*](..\chapter3\03_Types.html#type) **!** > *隐式解析可选类型* → [*类型*](../chapter3/03_Types.html#type) **!**
<a name="protocol_composition_type"></a> <a name="protocol_composition_type"></a>
##协议合成类型 ##协议合成类型
@ -233,9 +237,9 @@ protocol<Protocol 1, Procotol 2>
协议合成列表中的每项必须是协议名或协议合成类型的类型别名。如果列表为空,它就会指定一个空协议合成列表,这样每个类型都能遵循。 协议合成列表中的每项必须是协议名或协议合成类型的类型别名。如果列表为空,它就会指定一个空协议合成列表,这样每个类型都能遵循。
> 协议合成类型语法 > 协议合成类型语法
> *协议合成类型* → **protocol** **<** [*协议标识符列表*](..\chapter3\03_Types.html#protocol_identifier_list) _可选_ **>** > *协议合成类型* → **protocol** **<** [*协议标识符列表*](../chapter3/03_Types.html#protocol_identifier_list) _可选_ **>**
> *协议标识符列表* → [*协议标识符*](..\chapter3\03_Types.html#protocol_identifier) | [*协议标识符*](..\chapter3\03_Types.html#protocol_identifier) **,** [*协议标识符列表*](..\chapter3\03_Types.html#protocol_identifier_list) > *协议标识符列表* → [*协议标识符*](../chapter3/03_Types.html#protocol_identifier) | [*协议标识符*](../chapter3/03_Types.html#protocol_identifier) **,** [*协议标识符列表*](../chapter3/03_Types.html#protocol_identifier_list)
> *协议标识符* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) > *协议标识符* → [*类型标识*](../chapter3/03_Types.html#type_identifier)
<a name="metatype_type"></a> <a name="metatype_type"></a>
##元类型 ##元类型
@ -268,7 +272,7 @@ someInstance.dynamicType.printClassName()
> 元(Metatype)类型语法 > 元(Metatype)类型语法
> *元类型* → [*类型*](..\chapter3\03_Types.html#type) **.** **Type** | [*类型*](..\chapter3\03_Types.html#type) **.** **Protocol** > *元类型* → [*类型*](../chapter3/03_Types.html#type) **.** **Type** | [*类型*](../chapter3/03_Types.html#type) **.** **Protocol**
<a name="type_inheritance_clause"></a> <a name="type_inheritance_clause"></a>
##类型继承子句 ##类型继承子句
@ -282,10 +286,10 @@ someInstance.dynamicType.printClassName()
枚举定义中的类型继承子句可以是一个协议列表或是指定原始值的枚举——一个单独的指定原始值类型的命名型类型。使用类型继承子句来指定原始值类型的枚举定义的例子见章节Raw Values。 枚举定义中的类型继承子句可以是一个协议列表或是指定原始值的枚举——一个单独的指定原始值类型的命名型类型。使用类型继承子句来指定原始值类型的枚举定义的例子见章节Raw Values。
> 类型继承子句语法 > 类型继承子句语法
> *类型继承子句* → **:** [*类需求*](..\chapter3\03_Types.html#class_requirement) **,** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list) > *类型继承子句* → **:** [*类需求*](../chapter3/03_Types.html#class_requirement) **,** [*类型继承列表*](../chapter3/03_Types.html#type_inheritance_list)
> *类型继承子句* → **:** [*类需求*](..\chapter3\03_Types.html#class_requirement) > *类型继承子句* → **:** [*类需求*](../chapter3/03_Types.html#class_requirement)
> *类型继承子句* → **:** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list) > *类型继承子句* → **:** [*类型继承列表*](../chapter3/03_Types.html#type_inheritance_list)
> *类型继承列表* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) | [*类型标识*](..\chapter3\03_Types.html#type_identifier) **,** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list) > *类型继承列表* → [*类型标识*](../chapter3/03_Types.html#type_identifier) | [*类型标识*](../chapter3/03_Types.html#type_identifier) **,** [*类型继承列表*](../chapter3/03_Types.html#type_inheritance_list)
> *类需求* → **类** > *类需求* → **类**
<a name="type_inference"></a> <a name="type_inference"></a>

View File

@ -1,6 +1,10 @@
> 1.0
> 翻译:[sg552](https://github.com/sg552) > 翻译:[sg552](https://github.com/sg552)
> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai) > 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[EudeMorgen](https://github.com/EudeMorgen)
# 表达式Expressions # 表达式Expressions
----------------- -----------------
@ -19,8 +23,8 @@ Swift 中存在四种表达式: 前缀prefix表达式二元binary
前缀表达式和二元表达式就是对某些表达式使用各种运算符operators。 主要表达式是最短小的表达式,它提供了获取(变量的)值的一种途径。 后缀表达式则允许你建立复杂的表达式,例如配合函数调用和成员访问。 每种表达式都在下面有详细论述。 前缀表达式和二元表达式就是对某些表达式使用各种运算符operators。 主要表达式是最短小的表达式,它提供了获取(变量的)值的一种途径。 后缀表达式则允许你建立复杂的表达式,例如配合函数调用和成员访问。 每种表达式都在下面有详细论述。
> 表达式语法 > 表达式语法
> *表达式* → [*试算子(try operator)*](..\chapter3\04_Expressions.html#*) _可选_ | [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) | [*二元表达式列表*](..\chapter3\04_Expressions.html#binary_expressions) _可选_ > *表达式* → [*试算子(try operator)*](../chapter3/04_Expressions.html#*) _可选_ | [*前置表达式*](../chapter3/04_Expressions.html#prefix_expression) | [*二元表达式列表*](../chapter3/04_Expressions.html#binary_expressions) _可选_
> *表达式列表* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*表达式*](..\chapter3\04_Expressions.html#expression) **,** [*表达式列表*](..\chapter3\04_Expressions.html#expression_list) > *表达式列表* → [*表达式*](../chapter3/04_Expressions.html#expression) | [*表达式*](../chapter3/04_Expressions.html#expression) **,** [*表达式列表*](../chapter3/04_Expressions.html#expression_list)
<a name="prefix_expressions"></a> <a name="prefix_expressions"></a>
## 前缀表达式Prefix Expressions ## 前缀表达式Prefix Expressions
@ -32,8 +36,8 @@ Swift 中存在四种表达式: 前缀prefix表达式二元binary
作为对上面标准库运算符的补充,你也可以对 某个函数的参数使用 '&'运算符。 更多信息,请参见: "In-Out parameters". 作为对上面标准库运算符的补充,你也可以对 某个函数的参数使用 '&'运算符。 更多信息,请参见: "In-Out parameters".
> 前置表达式语法 > 前置表达式语法
> *前置表达式* → [*前置运算符*](LexicalStructure.html#prefix_operator) _可选_ [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) > *前置表达式* → [*前置运算符*](LexicalStructure.html#prefix_operator) _可选_ [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression)
> *前置表达式* → [*写入写出(in-out)表达式*](..\chapter3\04_Expressions.html#in_out_expression) > *前置表达式* → [*写入写出(in-out)表达式*](../chapter3/04_Expressions.html#in_out_expression)
> *写入写出(in-out)表达式* → **&** [*标识符*](LexicalStructure.html#identifier) > *写入写出(in-out)表达式* → **&** [*标识符*](LexicalStructure.html#identifier)
<a name="try_operator"></a> <a name="try_operator"></a>
@ -59,11 +63,11 @@ try表达式由紧跟在可能会出错的表达式后面的`try`操作符组成
> 在解析时, 一个二元表达式表示为一个一级数组a flat list, 这个数组List根据运算符的先后顺序被转换成了一个tree. 例如: 2 + 3 * 5 首先被认为是: 2, + , `` 3``, *, 5. 随后它被转换成 tree 2 + 3 * 5 > 在解析时, 一个二元表达式表示为一个一级数组a flat list, 这个数组List根据运算符的先后顺序被转换成了一个tree. 例如: 2 + 3 * 5 首先被认为是: 2, + , `` 3``, *, 5. 随后它被转换成 tree 2 + 3 * 5
> 二元表达式语法 > 二元表达式语法
> *二元表达式* → [*二元运算符*](LexicalStructure.html#binary_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) > *二元表达式* → [*二元运算符*](LexicalStructure.html#binary_operator) [*前置表达式*](../chapter3/04_Expressions.html#prefix_expression)
> *二元表达式* → [*赋值运算符*](..\chapter3\04_Expressions.html#assignment_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) > *二元表达式* → [*赋值运算符*](../chapter3/04_Expressions.html#assignment_operator) [*前置表达式*](../chapter3/04_Expressions.html#prefix_expression)
> *二元表达式* → [*条件运算符*](..\chapter3\04_Expressions.html#conditional_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) > *二元表达式* → [*条件运算符*](../chapter3/04_Expressions.html#conditional_operator) [*前置表达式*](../chapter3/04_Expressions.html#prefix_expression)
> *二元表达式* → [*类型转换运算符*](..\chapter3\04_Expressions.html#type_casting_operator) > *二元表达式* → [*类型转换运算符*](../chapter3/04_Expressions.html#type_casting_operator)
> *二元表达式列表* → [*二元表达式*](..\chapter3\04_Expressions.html#binary_expression) [*二元表达式列表*](..\chapter3\04_Expressions.html#binary_expressions) _可选_ > *二元表达式列表* → [*二元表达式*](../chapter3/04_Expressions.html#binary_expression) [*二元表达式列表*](../chapter3/04_Expressions.html#binary_expressions) _可选_
> *赋值操作符* > *赋值操作符*
@ -98,7 +102,7 @@ try表达式由紧跟在可能会出错的表达式后面的`try`操作符组成
想看三元条件运算符的例子,请参见: Ternary Conditional Operator. 想看三元条件运算符的例子,请参见: Ternary Conditional Operator.
> 三元条件运算符语法 > 三元条件运算符语法
> *三元条件运算符* → **?** [*表达式*](..\chapter3\04_Expressions.html#expression) **:** > *三元条件运算符* → **?** [*表达式*](../chapter3/04_Expressions.html#expression) **:**
<a name="type-casting_operators"></a> <a name="type-casting_operators"></a>
## 类型转换运算符Type-Casting Operators ## 类型转换运算符Type-Casting Operators
@ -136,10 +140,10 @@ f(x as Any)
关于类型转换的更多内容和例子,请参见: Type Casting. 关于类型转换的更多内容和例子,请参见: Type Casting.
> 类型转换运算符(type-casting-operator)语法 > 类型转换运算符(type-casting-operator)语法
> *类型转换运算符* → **is** [*类型*](..\chapter3\03_Types.html#type) > *类型转换运算符* → **is** [*类型*](../chapter3/03_Types.html#type)
> *类型转换运算符* → **as** [*类型*](..\chapter3\03_Types.html#type) > *类型转换运算符* → **as** [*类型*](../chapter3/03_Types.html#type)
> *类型转换运算符* → **is** **?** [*类型*](..\chapter3\03_Types.html#type) > *类型转换运算符* → **is** **?** [*类型*](../chapter3/03_Types.html#type)
> *类型转换运算符* → **as** **!** [*类型*](..\chapter3\03_Types.html#type) > *类型转换运算符* → **as** **!** [*类型*](../chapter3/03_Types.html#type)
<a name="primary_expressions"></a> <a name="primary_expressions"></a>
## 主表达式Primary Expressions ## 主表达式Primary Expressions
@ -148,13 +152,13 @@ f(x as Any)
> 主表达式语法 > 主表达式语法
> *主表达式* → [*标识符*](LexicalStructure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ > *主表达式* → [*标识符*](LexicalStructure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_
> *主表达式* → [*字符型表达式*](..\chapter3\04_Expressions.html#literal_expression) > *主表达式* → [*字符型表达式*](../chapter3/04_Expressions.html#literal_expression)
> *主表达式* → [*self表达式*](..\chapter3\04_Expressions.html#self_expression) > *主表达式* → [*self表达式*](../chapter3/04_Expressions.html#self_expression)
> *主表达式* → [*超类表达式*](..\chapter3\04_Expressions.html#superclass_expression) > *主表达式* → [*超类表达式*](../chapter3/04_Expressions.html#superclass_expression)
> *主表达式* → [*闭包表达式*](..\chapter3\04_Expressions.html#closure_expression) > *主表达式* → [*闭包表达式*](../chapter3/04_Expressions.html#closure_expression)
> *主表达式* → [*圆括号表达式*](..\chapter3\04_Expressions.html#parenthesized_expression) > *主表达式* → [*圆括号表达式*](../chapter3/04_Expressions.html#parenthesized_expression)
> *主表达式* → [*隐式成员表达式*](..\chapter3\04_Expressions.html#implicit_member_expression) > *主表达式* → [*隐式成员表达式*](../chapter3/04_Expressions.html#implicit_member_expression)
> *主表达式* → [*通配符表达式*](..\chapter3\04_Expressions.html#wildcard_expression) > *主表达式* → [*通配符表达式*](../chapter3/04_Expressions.html#wildcard_expression)
### 字符型表达式Literal Expression ### 字符型表达式Literal Expression
@ -162,10 +166,10 @@ f(x as Any)
字符Literal | 类型Type | 值Value 字符Literal | 类型Type | 值Value
------------- | ---------- | ---------- ------------- | ---------- | ----------
\__FILE__ | String | 所在的文件名 /__FILE__ | String | 所在的文件名
\__LINE__ | Int | 所在的行数 /__LINE__ | Int | 所在的行数
\__COLUMN__ | Int | 所在的列数 /__COLUMN__ | Int | 所在的列数
\__FUNCTION__ | String | 所在的function 的名字 /__FUNCTION__ | String | 所在的function 的名字
在某个函数function`__FUNCTION__` 会返回当前函数的名字。 在某个方法method它会返回当前方法的名字。 在某个property 的getter/setter中会返回这个属性的名字。 在特殊的成员如init/subscript中 会返回这个关键字的名字在某个文件的顶端the top level of a file它返回的是当前module的名字。 在某个函数function`__FUNCTION__` 会返回当前函数的名字。 在某个方法method它会返回当前方法的名字。 在某个property 的getter/setter中会返回这个属性的名字。 在特殊的成员如init/subscript中 会返回这个关键字的名字在某个文件的顶端the top level of a file它返回的是当前module的名字。
@ -201,14 +205,14 @@ var emptyDictionary: [String: Double]=[:]
``` ```
> 字面量表达式语法 > 字面量表达式语法
> *字面量表达式* → [*字面量*](LexicalStructure.html#literal) > *字面量表达式* → [*字面量*](LexicalStructure.html#literal)
> *字面量表达式* → [*数组字面量*](..\chapter3\04_Expressions.html#array_literal) | [*字典字面量*](..\chapter3\04_Expressions.html#dictionary_literal) > *字面量表达式* → [*数组字面量*](../chapter3/04_Expressions.html#array_literal) | [*字典字面量*](../chapter3/04_Expressions.html#dictionary_literal)
> *字面量表达式* → **&#95;&#95;FILE&#95;&#95;** | **&#95;&#95;LINE&#95;&#95;** | **&#95;&#95;COLUMN&#95;&#95;** | **&#95;&#95;FUNCTION&#95;&#95;** > *字面量表达式* → **&#95;&#95;FILE&#95;&#95;** | **&#95;&#95;LINE&#95;&#95;** | **&#95;&#95;COLUMN&#95;&#95;** | **&#95;&#95;FUNCTION&#95;&#95;**
> *数组字面量* → **[** [*数组字面量项列表*](..\chapter3\04_Expressions.html#array_literal_items) _可选_ **]** > *数组字面量* → **[** [*数组字面量项列表*](../chapter3/04_Expressions.html#array_literal_items) _可选_ **]**
> *数组字面量项列表* → [*数组字面量项*](..\chapter3\04_Expressions.html#array_literal_item) **,** _可选_ | [*数组字面量项*](..\chapter3\04_Expressions.html#array_literal_item) **,** [*数组字面量项列表*](..\chapter3\04_Expressions.html#array_literal_items) > *数组字面量项列表* → [*数组字面量项*](../chapter3/04_Expressions.html#array_literal_item) **,** _可选_ | [*数组字面量项*](../chapter3/04_Expressions.html#array_literal_item) **,** [*数组字面量项列表*](../chapter3/04_Expressions.html#array_literal_items)
> *数组字面量项* → [*表达式*](..\chapter3\04_Expressions.html#expression) > *数组字面量项* → [*表达式*](../chapter3/04_Expressions.html#expression)
> *字典字面量* → **[** [*字典字面量项列表*](..\chapter3\04_Expressions.html#dictionary_literal_items) **]** | **[** **:** **]** > *字典字面量* → **[** [*字典字面量项列表*](../chapter3/04_Expressions.html#dictionary_literal_items) **]** | **[** **:** **]**
> *字典字面量项列表* → [*字典字面量项*](..\chapter3\04_Expressions.html#dictionary_literal_item) **,** _可选_ | [*字典字面量项*](..\chapter3\04_Expressions.html#dictionary_literal_item) **,** [*字典字面量项列表*](..\chapter3\04_Expressions.html#dictionary_literal_items) > *字典字面量项列表* → [*字典字面量项*](../chapter3/04_Expressions.html#dictionary_literal_item) **,** _可选_ | [*字典字面量项*](../chapter3/04_Expressions.html#dictionary_literal_item) **,** [*字典字面量项列表*](../chapter3/04_Expressions.html#dictionary_literal_items)
> *字典字面量项* → [*表达式*](..\chapter3\04_Expressions.html#expression) **:** [*表达式*](..\chapter3\04_Expressions.html#expression) > *字典字面量项* → [*表达式*](../chapter3/04_Expressions.html#expression) **:** [*表达式*](../chapter3/04_Expressions.html#expression)
### self表达式Self Expression ### self表达式Self Expression
@ -217,8 +221,8 @@ self表达式是对 当前type 或者当前instance的引用。它的形式如
> self > self
> self.`member name` > self.`member name`
> self[`subscript index`] > self[`subscript index`]
> self`initializer arguments` > self(`initializer arguments`)
> self.init`initializer arguments` > self.init(`initializer arguments`)
如果在 initializer, subscript, instance method中self等同于当前type的instance. 在一个静态方法static method, 类方法class method self等同于当前的type. 如果在 initializer, subscript, instance method中self等同于当前type的instance. 在一个静态方法static method, 类方法class method self等同于当前的type.
@ -228,7 +232,7 @@ self表达式是对 当前type 或者当前instance的引用。它的形式如
```swift ```swift
class SomeClass { class SomeClass {
var greeting: String var greeting: String
initgreeting: String { init(greeting: String) {
self.greeting = greeting self.greeting = greeting
} }
} }
@ -239,8 +243,8 @@ class SomeClass {
```swift ```swift
struct Point { struct Point {
var x = 0.0, y = 0.0 var x = 0.0, y = 0.0
mutating func moveByXdeltaX: Double, y deltaY: Double { mutating func moveByX(deltaX: Double, y deltaY: Double) {
self = Pointx: x + deltaX, y: y + deltaY self = Point(x: x + deltaX, y: y + deltaY)
} }
} }
``` ```
@ -248,7 +252,7 @@ struct Point {
> Self 表达式语法 > Self 表达式语法
> *self表达式* → **self** > *self表达式* → **self**
> *self表达式* → **self** **.** [*标识符*](LexicalStructure.html#identifier) > *self表达式* → **self** **.** [*标识符*](LexicalStructure.html#identifier)
> *self表达式* → **self** **[** [*表达式*](..\chapter3\04_Expressions.html#expression) **]** > *self表达式* → **self** **[** [*表达式*](../chapter3/04_Expressions.html#expression) **]**
> *self表达式* → **self** **.** **init** > *self表达式* → **self** **.** **init**
### 超类表达式Superclass Expression ### 超类表达式Superclass Expression
@ -257,16 +261,16 @@ struct Point {
> super.`member name` > super.`member name`
> super[`subscript index`] > super[`subscript index`]
> super.init`initializer arguments` > super.init(`initializer arguments`)
形式1 用来访问超类的某个成员member. 形式2 用来访问该超类的 subscript 实现。 形式3 用来访问该超类的 initializer. 形式1 用来访问超类的某个成员member. 形式2 用来访问该超类的 subscript 实现。 形式3 用来访问该超类的 initializer.
子类subclass可以通过超类superclass表达式在它们的 member, subscripting 和 initializers 中来利用它们超类中的某些实现(既有的方法或者逻辑)。 子类subclass可以通过超类superclass表达式在它们的 member, subscripting 和 initializers 中来利用它们超类中的某些实现(既有的方法或者逻辑)。
> 超类(superclass)表达式语法 > 超类(superclass)表达式语法
> *超类表达式* → [*超类方法表达式*](..\chapter3\04_Expressions.html#superclass_method_expression) | [*超类下标表达式*](..\chapter3\04_Expressions.html#超类下标表达式) | [*超类构造器表达式*](..\chapter3\04_Expressions.html#superclass_initializer_expression) > *超类表达式* → [*超类方法表达式*](../chapter3/04_Expressions.html#superclass_method_expression) | [*超类下标表达式*](../chapter3/04_Expressions.html#超类下标表达式) | [*超类构造器表达式*](../chapter3/04_Expressions.html#superclass_initializer_expression)
> *超类方法表达式* → **super** **.** [*标识符*](LexicalStructure.html#identifier) > *超类方法表达式* → **super** **.** [*标识符*](LexicalStructure.html#identifier)
> *超类下标表达式* → **super** **[** [*表达式*](..\chapter3\04_Expressions.html#expression) **]** > *超类下标表达式* → **super** **[** [*表达式*](../chapter3/04_Expressions.html#expression) **]**
> *超类构造器表达式* → **super** **.** **init** > *超类构造器表达式* → **super** **.** **init**
### 闭包表达式Closure Expression ### 闭包表达式Closure Expression
@ -274,7 +278,7 @@ struct Point {
闭包closure 表达式可以建立一个闭包(在其他语言中也叫 lambda, 或者 匿名函数anonymous function. 跟函数function的声明一样 闭包closure包含了可执行的代码跟方法主体statement类似 以及接收capture的参数。 它的形式如下: 闭包closure 表达式可以建立一个闭包(在其他语言中也叫 lambda, 或者 匿名函数anonymous function. 跟函数function的声明一样 闭包closure包含了可执行的代码跟方法主体statement类似 以及接收capture的参数。 它的形式如下:
```swift ```swift
{ parameters -> return type in { (parameters) -> return type in
statements statements
} }
``` ```
@ -291,12 +295,12 @@ struct Point {
```swift ```swift
myFunction { myFunction {
x: Int, y: Int -> Int in (x: Int, y: Int) -> Int in
return x + y return x + y
} }
myFunction { myFunction {
x, y in (x, y) in
return x + y return x + y
} }
@ -312,28 +316,28 @@ myFunction { $0 + $1 }
在闭包的参数列表( capture list 参数可以声明为 'weak' 或者 'unowned' . 在闭包的参数列表( capture list 参数可以声明为 'weak' 或者 'unowned' .
```swift ```swift
myFunction { printself.title } // strong capture myFunction { print(self.title) } // strong capture
myFunction { [weak self] in printself!.title } // weak capture myFunction { [weak self] in print(self!.title) } // weak capture
myFunction { [unowned self] in printself.title } // unowned capture myFunction { [unowned self] in print(self.title) } // unowned capture
``` ```
在参数列表中,也可以使用任意表达式来赋值. 该表达式会在 闭包被执行时赋值然后按照不同的力度来获取这句话请慎重理解captured with the specified strength. 例如: 在参数列表中,也可以使用任意表达式来赋值. 该表达式会在 闭包被执行时赋值然后按照不同的力度来获取这句话请慎重理解captured with the specified strength. 例如:
```swift ```swift
// Weak capture of "self.parent" as "parent" // Weak capture of "self.parent" as "parent"
myFunction { [weak parent = self.parent] in printparent!.title } myFunction { [weak parent = self.parent] in print(parent!.title) }
``` ```
关于闭包表达式的更多信息和例子,请参见: Closure Expressions. 关于闭包表达式的更多信息和例子,请参见: Closure Expressions.
> 闭包表达式语法 > 闭包表达式语法
> *闭包表达式* → **{** [*闭包签名(Signational)*](..\chapter3\04_Expressions.html#closure_signature) _可选_ [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements) **}** > *闭包表达式* → **{** [*闭包签名(Signational)*](../chapter3/04_Expressions.html#closure_signature) _可选_ [*多条语句(Statements)*](../chapter3/10_Statements.html#statements) **}**
> *闭包签名(Signational)* → [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** > *闭包签名(Signational)* → [*参数子句*](../chapter3/05_Declarations.html#parameter_clause) [*函数结果*](../chapter3/05_Declarations.html#function_result) _可选_ **in**
> *闭包签名(Signational)* → [*标识符列表*](LexicalStructure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** > *闭包签名(Signational)* → [*标识符列表*](LexicalStructure.html#identifier_list) [*函数结果*](../chapter3/05_Declarations.html#function_result) _可选_ **in**
> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** > *闭包签名(Signational)* → [*捕获(Capature)列表*](../chapter3/04_Expressions.html#capture_list) [*参数子句*](../chapter3/05_Declarations.html#parameter_clause) [*函数结果*](../chapter3/05_Declarations.html#function_result) _可选_ **in**
> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) [*标识符列表*](LexicalStructure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in** > *闭包签名(Signational)* → [*捕获(Capature)列表*](../chapter3/04_Expressions.html#capture_list) [*标识符列表*](LexicalStructure.html#identifier_list) [*函数结果*](../chapter3/05_Declarations.html#function_result) _可选_ **in**
> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) **in** > *闭包签名(Signational)* → [*捕获(Capature)列表*](../chapter3/04_Expressions.html#capture_list) **in**
> *捕获(Capature)列表* → **[** [*捕获(Capature)说明符*](..\chapter3\04_Expressions.html#capture_specifier) [*表达式*](..\chapter3\04_Expressions.html#expression) **]** > *捕获(Capature)列表* → **[** [*捕获(Capature)说明符*](../chapter3/04_Expressions.html#capture_specifier) [*表达式*](../chapter3/04_Expressions.html#expression) **]**
> *捕获(Capature)说明符* → **weak** | **unowned** | **unowned(safe)** | **unowned(unsafe)** > *捕获(Capature)说明符* → **weak** | **unowned** | **unowned(safe)** | **unowned(unsafe)**
### 隐式成员表达式Implicit Member Expression ### 隐式成员表达式Implicit Member Expression
@ -350,7 +354,7 @@ x = .AnotherValue
``` ```
> 隐式成员表达式语法 > 隐式成员表达式语法
> *隐式成员表达式* → **.** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *隐式成员表达式* → **.** [*标识符*](../chapter3/02_Lexical_Structure.html#identifier)
### 圆括号表达式Parenthesized Expression ### 圆括号表达式Parenthesized Expression
@ -361,16 +365,16 @@ x = .AnotherValue
圆括号表达式用来建立tuples 然后把它做为参数传递给 function. 如果某个圆括号表达式中只有一个 子表达式那么它的type就是 子表达式的type。例如 1的 type是Int, 而不是Int 圆括号表达式用来建立tuples 然后把它做为参数传递给 function. 如果某个圆括号表达式中只有一个 子表达式那么它的type就是 子表达式的type。例如 1的 type是Int, 而不是Int
> 圆括号表达式(Parenthesized Expression)语法 > 圆括号表达式(Parenthesized Expression)语法
> *圆括号表达式* → **(** [*表达式元素列表*](..\chapter3\04_Expressions.html#expression_element_list) _可选_ **)** > *圆括号表达式* → **(** [*表达式元素列表*](../chapter3/04_Expressions.html#expression_element_list) _可选_ **)**
> *表达式元素列表* → [*表达式元素*](..\chapter3\04_Expressions.html#expression_element) | [*表达式元素*](..\chapter3\04_Expressions.html#expression_element) **,** [*表达式元素列表*](..\chapter3\04_Expressions.html#expression_element_list) > *表达式元素列表* → [*表达式元素*](../chapter3/04_Expressions.html#expression_element) | [*表达式元素*](../chapter3/04_Expressions.html#expression_element) **,** [*表达式元素列表*](../chapter3/04_Expressions.html#expression_element_list)
> *表达式元素* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) **:** [*表达式*](..\chapter3\04_Expressions.html#expression) > *表达式元素* → [*表达式*](../chapter3/04_Expressions.html#expression) | [*标识符*](../chapter3/02_Lexical_Structure.html#identifier) **:** [*表达式*](../chapter3/04_Expressions.html#expression)
### 通配符表达式Wildcard Expression ### 通配符表达式Wildcard Expression
通配符表达式用来忽略传递进来的某个参数。例如下面的代码中10被传递给x, 20被忽略译注好奇葩的语法。。。 通配符表达式用来忽略传递进来的某个参数。例如下面的代码中10被传递给x, 20被忽略译注好奇葩的语法。。。
```swift ```swift
x, _ = 10, 20 (x, _) = (10, 20)
// x is 10, 20 is ignored // x is 10, 20 is ignored
``` ```
@ -390,56 +394,53 @@ Swift 标准库提供了下列后缀表达式:
对于这些操作符的使用,请参见: Basic Operators and Advanced Operators 对于这些操作符的使用,请参见: Basic Operators and Advanced Operators
> 后置表达式语法 > 后置表达式语法
> *后置表达式* → [*主表达式*](..\chapter3\04_Expressions.html#primary_expression) > *后置表达式* → [*主表达式*](../chapter3/04_Expressions.html#primary_expression)
> *后置表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) [*后置运算符*](..\chapter3\02_Lexical_Structure.html#postfix_operator) > *后置表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) [*后置运算符*](../chapter3/02_Lexical_Structure.html#postfix_operator)
> *后置表达式* → [*函数调用表达式*](..\chapter3\04_Expressions.html#function_call_expression) > *后置表达式* → [*函数调用表达式*](../chapter3/04_Expressions.html#function_call_expression)
> *后置表达式* → [*构造器表达式*](..\chapter3\04_Expressions.html#initializer_expression) > *后置表达式* → [*构造器表达式*](../chapter3/04_Expressions.html#initializer_expression)
> *后置表达式* → [*显示成员表达式*](..\chapter3\04_Expressions.html#explicit_member_expression) > *后置表达式* → [*显示成员表达式*](../chapter3/04_Expressions.html#explicit_member_expression)
> *后置表达式* → [*后置self表达式*](..\chapter3\04_Expressions.html#postfix_self_expression) > *后置表达式* → [*后置self表达式*](../chapter3/04_Expressions.html#postfix_self_expression)
> *后置表达式* → [*动态类型表达式*](..\chapter3\04_Expressions.html#dynamic_type_expression) > *后置表达式* → [*动态类型表达式*](../chapter3/04_Expressions.html#dynamic_type_expression)
> *后置表达式* → [*下标表达式*](..\chapter3\04_Expressions.html#subscript_expression) > *后置表达式* → [*下标表达式*](../chapter3/04_Expressions.html#subscript_expression)
> *后置表达式* → [*强制取值(Forced Value)表达式*](..\chapter3\04_Expressions.html#forced_value_expression) > *后置表达式* → [*强制取值(Forced Value)表达式*](../chapter3/04_Expressions.html#forced_value_expression)
> *后置表达式* → [*可选链(Optional Chaining)表达式*](..\chapter3\04_Expressions.html#optional_chaining_expression) > *后置表达式* → [*可选链(Optional Chaining)表达式*](../chapter3/04_Expressions.html#optional_chaining_expression)
### 函数调用表达式Function Call Expression ### 函数调用表达式Function Call Expression
函数调用表达式由函数名和参数列表组成。它的形式如下: 函数调用表达式由函数名和参数列表组成。它的形式如下:
> `function name``argument value 1`, `argument value 2` > `function name`(`argument value 1`, `argument value 2`)
The function name can be any expression whose value is of a function type.
(不用翻译了, 太罗嗦)
如果该function 的声明中指定了参数的名字,那么在调用的时候也必须得写出来. 例如: 如果该function 的声明中指定了参数的名字,那么在调用的时候也必须得写出来. 例如:
> `function name``argument name 1`: `argument value 1`, `argument name 2`: `argument value 2` > `function name`(`argument name 1`: `argument value 1`, `argument name 2`: `argument value 2`)
可以在 函数调用表达式的尾部(最后一个参数之后)加上 一个闭包closure 该闭包会被目标函数理解并执行。它具有如下两种写法: 可以在 函数调用表达式的尾部(最后一个参数之后)加上 一个闭包closure 该闭包会被目标函数理解并执行。它具有如下两种写法:
```swift ```swift
// someFunction takes an integer and a closure as its arguments // someFunction takes an integer and a closure as its arguments
someFunctionx, {$0 == 13} someFunction(x, {$0 == 13}+
someFunctionx {$0 == 13} someFunction(x) {$0 == 13}
``` ```
如果闭包是该函数的唯一参数,那么圆括号可以省略。 如果闭包是该函数的唯一参数,那么圆括号可以省略。
```swift ```swift
// someFunction takes a closure as its only argument // someFunction takes a closure as its only argument
myData.someMethod {$0 == 13} myData.someMethod() {$0 == 13}
myData.someMethod {$0 == 13} myData.someMethod {$0 == 13}
``` ```
> 函数调用表达式语法 > 函数调用表达式语法
> *函数调用表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) [*圆括号表达式*](..\chapter3\04_Expressions.html#parenthesized_expression) > *函数调用表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) [*圆括号表达式*](../chapter3/04_Expressions.html#parenthesized_expression)
> *函数调用表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) [*圆括号表达式*](..\chapter3\04_Expressions.html#parenthesized_expression) _可选_ [*后置闭包(Trailing Closure)*](..\chapter3\04_Expressions.html#trailing_closure) > *函数调用表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) [*圆括号表达式*](../chapter3/04_Expressions.html#parenthesized_expression) _可选_ [*后置闭包(Trailing Closure)*](../chapter3/04_Expressions.html#trailing_closure)
> *后置闭包(Trailing Closure)* → [*闭包表达式*](..\chapter3\04_Expressions.html#closure_expression) > *后置闭包(Trailing Closure)* → [*闭包表达式*](../chapter3/04_Expressions.html#closure_expression)
### 初始化函数表达式Initializer Expression ### 初始化函数表达式Initializer Expression
Initializer表达式用来给某个Type初始化。 它的形式如下: Initializer表达式用来给某个Type初始化。 它的形式如下:
> `expression`.init`initializer arguments` > `expression`.init(`initializer arguments`)
Initializer表达式用来给某个Type初始化。 跟函数function不同 initializer 不能返回值。 Initializer表达式用来给某个Type初始化。 跟函数function不同 initializer 不能返回值。
@ -452,15 +453,15 @@ var y = SomeClass.init // error
```swift ```swift
class SomeSubClass: SomeSuperClass { class SomeSubClass: SomeSuperClass {
init { init() {
// subclass initialization goes here // subclass initialization goes here
super.init super.init()
} }
} }
``` ```
> 构造器表达式语法 > 构造器表达式语法
> *构造器表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** **init** > *构造器表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) **.** **init**
### 显式成员表达式Explicit Member Expression ### 显式成员表达式Explicit Member Expression
@ -474,23 +475,23 @@ class SomeSubClass: SomeSuperClass {
class SomeClass { class SomeClass {
var someProperty = 42 var someProperty = 42
} }
let c = SomeClass let c = SomeClass()
let y = c.someProperty // Member access let y = c.someProperty // Member access
``` ```
对于tuple, 要根据它们出现的顺序0, 1, 2...)来使用: 对于tuple, 要根据它们出现的顺序0, 1, 2...)来使用:
```swift ```swift
var t = 10, 20, 30 var t = (10, 20, 30)
t.0 = t.1 t.0 = t.1
// Now t is 20, 20, 30 // Now t is (20, 20, 30)
``` ```
对于某个module的member的调用只能调用在top-level声明中的member. 对于某个module的member的调用只能调用在top-level声明中的member.
> 显式成员表达式语法 > 显式成员表达式语法
> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) > *显示成员表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) **.** [*十进制数字*](../chapter3/02_Lexical_Structure.html#decimal_digit)
> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ > *显示成员表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) **.** [*标识符*](../chapter3/02_Lexical_Structure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_
### 后缀self表达式Postfix Self Expression ### 后缀self表达式Postfix Self Expression
@ -504,7 +505,7 @@ t.0 = t.1
形式2返回对应的type。我们可以用它来动态的获取某个instance的type。 形式2返回对应的type。我们可以用它来动态的获取某个instance的type。
> 后置Self 表达式语法 > 后置Self 表达式语法
> *后置self表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** **self** > *后置self表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) **.** **self**
### dynamic表达式Dynamic Type Expression ### dynamic表达式Dynamic Type Expression
@ -518,25 +519,25 @@ dynamicType 表达式由 某个表达式 + '.dynamicType' 组成。
```swift ```swift
class SomeBaseClass { class SomeBaseClass {
class func printClassName { class func printClassName() {
println"SomeBaseClass" println("SomeBaseClass")
} }
} }
class SomeSubClass: SomeBaseClass { class SomeSubClass: SomeBaseClass {
override class func printClassName { override class func printClassName() {
println"SomeSubClass" println("SomeSubClass")
} }
} }
let someInstance: SomeBaseClass = SomeSubClass let someInstance: SomeBaseClass = SomeSubClass()
// someInstance is of type SomeBaseClass at compile time, but // someInstance is of type SomeBaseClass at compile time, but
// someInstance is of type SomeSubClass at runtime // someInstance is of type SomeSubClass at runtime
someInstance.dynamicType.printClassName someInstance.dynamicType.printClassName()
// prints "SomeSubClass" // prints "SomeSubClass"
``` ```
> 动态类型表达式语法 > 动态类型表达式语法
> *动态类型表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** **dynamicType** > *动态类型表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) **.** **dynamicType**
### 下标脚本表达式Subscript Expression ### 下标脚本表达式Subscript Expression
@ -549,7 +550,7 @@ someInstance.dynamicType.printClassName
关于subscript的声明请参见 Protocol Subscript Declaration. 关于subscript的声明请参见 Protocol Subscript Declaration.
> 附属脚本表达式语法 > 附属脚本表达式语法
> *附属脚本表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **[** [*表达式列表*](..\chapter3\04_Expressions.html#expression_list) **]** > *附属脚本表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) **[** [*表达式列表*](../chapter3/04_Expressions.html#expression_list) **]**
### 强制取值表达式Forced-Value Expression ### 强制取值表达式Forced-Value Expression
@ -570,7 +571,7 @@ someDictionary["a"]![0] = 100
``` ```
> 强制取值(Forced Value)语法 > 强制取值(Forced Value)语法
> *强制取值(Forced Value)表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **!** > *强制取值(Forced Value)表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) **!**
### 可选链表达式Optional-Chaining Expression ### 可选链表达式Optional-Chaining Expression
@ -586,14 +587,14 @@ someDictionary["a"]![0] = 100
```swift ```swift
var c: SomeClass? var c: SomeClass?
var result: Bool? = c?.property.performAction var result: Bool? = c?.property.performAction()
``` ```
如果不使用可选链表达式,那么 上面例子的代码跟下面例子等价: 如果不使用可选链表达式,那么 上面例子的代码跟下面例子等价:
```swift ```swift
if let unwrappedC = c { if let unwrappedC = c {
result = unwrappedC.property.performAction result = unwrappedC.property.performAction()
} }
``` ```
后缀'?' 返回目标表达式的值可能会被修改,可能是由于出现了赋值,也有可能是出现异常而产生的修改。如果可选链表达式为`nil`,则表达式右边的复制操作不会被执行。比如: 后缀'?' 返回目标表达式的值可能会被修改,可能是由于出现了赋值,也有可能是出现异常而产生的修改。如果可选链表达式为`nil`,则表达式右边的复制操作不会被执行。比如:
@ -614,4 +615,4 @@ someDictionary["a"]?[0] = someFunctionWithSideEffects()
> 可选链表达式语法 > 可选链表达式语法
> *可选链表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **?** > *可选链表达式* → [*后置表达式*](../chapter3/04_Expressions.html#postfix_expression) **?**

View File

@ -1,8 +1,12 @@
> 1.0
> 翻译:[marsprince](https://github.com/marsprince) [Lenhoon](https://github.com/marsprince)[(微博)](http://www.weibo.com/lenhoon) > 翻译:[marsprince](https://github.com/marsprince) [Lenhoon](https://github.com/marsprince)[(微博)](http://www.weibo.com/lenhoon)
> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai) > 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[Lenhoon](https://github.com/Lenhoon)
<a name="declarations"></a> <a name="declarations"></a>
# 声明 # 声明
----------------- -----------------
本页包含内容: 本页包含内容:
@ -84,9 +88,9 @@ Swift的源文件中的顶级代码由零个或多个语句声明和表达式
<a name="grammer_of_an_import_declaration"></a> <a name="grammer_of_an_import_declaration"></a>
> 导入(Import)声明语法 > 导入(Import)声明语法
> *导入声明* → [*特性(attributes)列表*](TODO) _可选_ **import** [*导入类型*](..\chapter3\05_Declarations.html#import_kind) _可选_ [*导入路径*](..\chapter3\05_Declarations.html#import_path) > *导入声明* → [*特性(attributes)列表*](TODO) _可选_ **import** [*导入类型*](../chapter3/05_Declarations.html#import_kind) _可选_ [*导入路径*](../chapter3/05_Declarations.html#import_path)
> *导入类型* → **typealias** | **struct** | **class** | **enum** | **protocol** | **var** | **func** > *导入类型* → **typealias** | **struct** | **class** | **enum** | **protocol** | **var** | **func**
> *导入路径* → [*导入路径标识符*](..\chapter3\05_Declarations.html#import_path_identifier) | [*导入路径标识符*](..\chapter3\05_Declarations.html#import_path_identifier) **.** [*导入路径*](..\chapter3\05_Declarations.html#import_path) > *导入路径* → [*导入路径标识符*](../chapter3/05_Declarations.html#import_path_identifier) | [*导入路径标识符*](../chapter3/05_Declarations.html#import_path_identifier) **.** [*导入路径*](../chapter3/05_Declarations.html#import_path)
> *导入路径标识符* → [*标识符*](TODO) | [*运算符*](TODO) > *导入路径标识符* → [*标识符*](TODO) | [*运算符*](TODO)
<a name="constant_declaration"></a> <a name="constant_declaration"></a>
@ -96,9 +100,9 @@ Swift的源文件中的顶级代码由零个或多个语句声明和表达式
> let `constant name`: `type` = `expression` > let `constant name`: `type` = `expression`
当常量的值被给定后,常量就将*常量名称(constant name)*和*表达式(expression)*初始值不变的结合在了一起,而且不能更改。 当常量的值被给定后,常量就将*常量名称(constant name)*和*表达式(expression)*初始值不变的结合在了一起,而且不能更改。
这意味着如果常量以类的形式被初始化,类本身的内容是可以改变的,但是常量和类之间的结合关系是不能改变的。 这意味着如果常量以类的形式被初始化,类本身的内容是可以改变的,但是常量和类之间的结合关系是不能改变的。
当一个常量被声明为全局变量,它必须被给定一个初始值。当一个常量在类或者结构体中被声明时,它被认为是一个*常量属性(constant property)*。常量并不是可计算的属性因此不包含getters和setters。 当一个常量被声明为全局变量,它必须被给定一个初始值。当一个常量在类或者结构体中被声明时,它被认为是一个*常量属性(constant property)*。常量并不是可计算的属性因此不包含getters和setters。
@ -111,9 +115,9 @@ let (firstNumber, secondNumber) = (10, 42)
在上例中,`firstNumber`是一个值为`10`的常量,`secnodeName`是一个值为`42`的常量。所有常量都可以独立的使用: 在上例中,`firstNumber`是一个值为`10`的常量,`secnodeName`是一个值为`42`的常量。所有常量都可以独立的使用:
```swift ```swift
println("The first number is \(firstNumber).") println("The first number is /(firstNumber).")
// prints "The first number is 10." // prints "The first number is 10."
println("The second number is \(secondNumber).") println("The second number is /(secondNumber).")
// prints "The second number is 42." // prints "The second number is 42."
``` ```
@ -122,26 +126,26 @@ println("The second number is \(secondNumber).")
声明一个常量类型属性要使用关键字`static`声明修饰符。类型属性在[类型属性(Type Properties)](TODO)中有介绍。 声明一个常量类型属性要使用关键字`static`声明修饰符。类型属性在[类型属性(Type Properties)](TODO)中有介绍。
如果还想获得更多关于常量的信息或者想在使用中获得帮助,请查看[常量和变量(Constants and Variables)](TODO)和[存储属性(Stored Properties)](TODO)等节。 如果还想获得更多关于常量的信息或者想在使用中获得帮助,请查看[常量和变量(Constants and Variables)](TODO)和[存储属性(Stored Properties)](TODO)等节。
<a name="grammer_of_a_constant_declaration"></a> <a name="grammer_of_a_constant_declaration"></a>
> 常数声明语法 > 常数声明语法
> *常量声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修饰符(Specifiers)列表*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **let** [*模式构造器列表*](..\chapter3\05_Declarations.html#pattern_initializer_list) > *常量声明* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*声明修饰符(Specifiers)列表*](../chapter3/05_Declarations.html#declaration_specifiers) _可选_ **let** [*模式构造器列表*](../chapter3/05_Declarations.html#pattern_initializer_list)
> *模式构造器列表* → [*模式构造器*](..\chapter3\05_Declarations.html#pattern_initializer) | [*模式构造器*](..\chapter3\05_Declarations.html#pattern_initializer) **,** [*模式构造器列表*](..\chapter3\05_Declarations.html#pattern_initializer_list) > *模式构造器列表* → [*模式构造器*](../chapter3/05_Declarations.html#pattern_initializer) | [*模式构造器*](../chapter3/05_Declarations.html#pattern_initializer) **,** [*模式构造器列表*](../chapter3/05_Declarations.html#pattern_initializer_list)
> *模式构造器* → [*模式*](..\chapter3\07_Patterns.html#pattern) [*构造器*](..\chapter3\05_Declarations.html#initializer) _可选_ > *模式构造器* → [*模式*](../chapter3/07_Patterns.html#pattern) [*构造器*](../chapter3/05_Declarations.html#initializer) _可选_
> *构造器* → **=** [*表达式*](..\chapter3\04_Expressions.html#expression) > *构造器* → **=** [*表达式*](../chapter3/04_Expressions.html#expression)
<a name="variable_declaration"></a> <a name="variable_declaration"></a>
##变量声明 ##变量声明
*变量声明(variable declaration)*可以在程序里声明一个变量,它以关键字`var`来声明。 *变量声明(variable declaration)*可以在程序里声明一个变量,它以关键字`var`来声明。
变量声明有几种不同的形式声明不同种类的命名值和计算型值,如存储和计算变量和属性,存储变量和属性监视,和静态变量属性。所使用的声明形式取决于变量所声明的范围和打算声明的变量类型。 变量声明有几种不同的形式声明不同种类的命名值和计算型值,如存储和计算变量和属性,存储变量和属性监视,和静态变量属性。所使用的声明形式取决于变量所声明的范围和打算声明的变量类型。
>注意: >注意:
>也可以在协议声明的上下文声明属性,详情参见[协议属性声明(Protocal Property Declaration)](TODO)。 >也可以在协议声明的上下文声明属性,详情参见[协议属性声明(Protocal Property Declaration)](TODO)。
可以重载一个子类中的属性,通过使用'override'声明修饰符来标记子类的属性声明,[重写(Overriding)](TODO)中有所介绍。 可以重载一个子类中的属性,通过使用'override'声明修饰符来标记子类的属性声明,[重写(Overriding)](TODO)中有所介绍。
<a name="stored_variables_and_stored_variable_properties"></a> <a name="stored_variables_and_stored_variable_properties"></a>
###存储型变量和存储型属性 ###存储型变量和存储型属性
@ -157,7 +161,7 @@ println("The second number is \(secondNumber).")
对于常量的定义,如果*变量名字variable name*是一个元组tuple元组中每一项的名称都要和初始化*表达式(expression)*中的相应值一致。 对于常量的定义,如果*变量名字variable name*是一个元组tuple元组中每一项的名称都要和初始化*表达式(expression)*中的相应值一致。
正如名字一样,存储型变量的值或存储型变量属性存储在内存中。 正如名字一样,存储型变量的值或存储型变量属性存储在内存中。
<a name="computed_variables_and_computed_properties"></a> <a name="computed_variables_and_computed_properties"></a>
###计算型变量和计算型属性 ###计算型变量和计算型属性
@ -182,7 +186,7 @@ setter的名字和圆括号内的语句是可选的。如果写了一个setter
不像存储型变量和存储型属性那样,计算型属性和计算型变量的值不存储在内存中。 不像存储型变量和存储型属性那样,计算型属性和计算型变量的值不存储在内存中。
获得更多信息,查看更多关于计算型属性的例子,请查看[计算型属性(Computed Properties)](TODO)一节。 获得更多信息,查看更多关于计算型属性的例子,请查看[计算型属性(Computed Properties)](TODO)一节。
<a name="stored_variable_observers_and_property_observers"></a> <a name="stored_variable_observers_and_property_observers"></a>
###存储型变量监视器和属性监视器 ###存储型变量监视器和属性监视器
@ -215,8 +219,8 @@ setter的名字和圆括号内的语句是可选的。如果写了一个setter
当提供一个`willset`语句时,`didset`语句是可选的。同样的,在提供了一个`didset`语句时,`willset`语句是可选的。 当提供一个`willset`语句时,`didset`语句是可选的。同样的,在提供了一个`didset`语句时,`willset`语句是可选的。
获得更多信息,查看如何使用属性监视器的例子,请查看[属性监视器(Property Observers)](TODO)一节。 获得更多信息,查看如何使用属性监视器的例子,请查看[属性监视器(Property Observers)](TODO)一节。
声明修饰符 声明修饰符
<a name="type_variable_properties"></a> <a name="type_variable_properties"></a>
###类型变量属性 ###类型变量属性
@ -225,30 +229,30 @@ setter的名字和圆括号内的语句是可选的。如果写了一个setter
>>注意 >>注意
>> >>
>在一个类声明中,关键字`static`与用声明修饰符`class``final`去标记一个声明的效果相同 >在一个类声明中,关键字`static`与用声明修饰符`class``final`去标记一个声明的效果相同
<a name="grammer_of_a_variable_declaration"></a> <a name="grammer_of_a_variable_declaration"></a>
> 变量声明语法 > 变量声明语法
> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*模式构造器列表*](..\chapter3\05_Declarations.html#pattern_initializer_list) > *变量声明* → [*变量声明头(Head)*](../chapter3/05_Declarations.html#variable_declaration_head) [*模式构造器列表*](../chapter3/05_Declarations.html#pattern_initializer_list)
> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型标注*](..\chapter3\03_Types.html#type_annotation) [*代码块*](..\chapter3\05_Declarations.html#code_block) > *变量声明* → [*变量声明头(Head)*](../chapter3/05_Declarations.html#variable_declaration_head) [*变量名*](../chapter3/05_Declarations.html#variable_name) [*类型标注*](../chapter3/03_Types.html#type_annotation) [*代码块*](../chapter3/05_Declarations.html#code_block)
> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型标注*](..\chapter3\03_Types.html#type_annotation) [*getter-setter块*](..\chapter3\05_Declarations.html#getter_setter_block) > *变量声明* → [*变量声明头(Head)*](../chapter3/05_Declarations.html#variable_declaration_head) [*变量名*](../chapter3/05_Declarations.html#variable_name) [*类型标注*](../chapter3/03_Types.html#type_annotation) [*getter-setter块*](../chapter3/05_Declarations.html#getter_setter_block)
> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型标注*](..\chapter3\03_Types.html#type_annotation) [*getter-setter关键字(Keyword)块*](..\chapter3\05_Declarations.html#getter_setter_keyword_block) > *变量声明* → [*变量声明头(Head)*](../chapter3/05_Declarations.html#variable_declaration_head) [*变量名*](../chapter3/05_Declarations.html#variable_name) [*类型标注*](../chapter3/03_Types.html#type_annotation) [*getter-setter关键字(Keyword)块*](../chapter3/05_Declarations.html#getter_setter_keyword_block)
> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*构造器*](..\chapter3\05_Declarations.html#initializer) [*willSet-didSet代码块*](..\chapter3\05_Declarations.html#willSet_didSet_block) > *变量声明* → [*变量声明头(Head)*](../chapter3/05_Declarations.html#variable_declaration_head) [*变量名*](../chapter3/05_Declarations.html#variable_name) [*构造器*](../chapter3/05_Declarations.html#initializer) [*willSet-didSet代码块*](../chapter3/05_Declarations.html#willSet_didSet_block)
> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型标注*](..\chapter3\03_Types.html#type_annotation) [*构造器*](..\chapter3\05_Declarations.html#initializer) _可选_ [*willSet-didSet代码块*](..\chapter3\05_Declarations.html#willSet_didSet_block) > *变量声明* → [*变量声明头(Head)*](../chapter3/05_Declarations.html#variable_declaration_head) [*变量名*](../chapter3/05_Declarations.html#variable_name) [*类型标注*](../chapter3/03_Types.html#type_annotation) [*构造器*](../chapter3/05_Declarations.html#initializer) _可选_ [*willSet-didSet代码块*](../chapter3/05_Declarations.html#willSet_didSet_block)
> *变量声明头(Head)* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修饰符(Specifiers)列表*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **var** > *变量声明头(Head)* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*声明修饰符(Specifiers)列表*](../chapter3/05_Declarations.html#declaration_specifiers) _可选_ **var**
> *变量名称* → [*标识符*](LexicalStructure.html#identifier) > *变量名称* → [*标识符*](LexicalStructure.html#identifier)
> *getter-setter块* → **{** [*getter子句*](..\chapter3\05_Declarations.html#getter_clause) [*setter子句*](..\chapter3\05_Declarations.html#setter_clause) _可选_ **}** > *getter-setter块* → **{** [*getter子句*](../chapter3/05_Declarations.html#getter_clause) [*setter子句*](../chapter3/05_Declarations.html#setter_clause) _可选_ **}**
> *getter-setter块* → **{** [*setter子句*](..\chapter3\05_Declarations.html#setter_clause) [*getter子句*](..\chapter3\05_Declarations.html#getter_clause) **}** > *getter-setter块* → **{** [*setter子句*](../chapter3/05_Declarations.html#setter_clause) [*getter子句*](../chapter3/05_Declarations.html#getter_clause) **}**
> *getter子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **get** [*代码块*](..\chapter3\05_Declarations.html#code_block) > *getter子句* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ **get** [*代码块*](../chapter3/05_Declarations.html#code_block)
> *setter子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **set** [*setter名称*](..\chapter3\05_Declarations.html#setter_name) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block) > *setter子句* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ **set** [*setter名称*](../chapter3/05_Declarations.html#setter_name) _可选_ [*代码块*](../chapter3/05_Declarations.html#code_block)
> *setter名称* → **(** [*标识符*](LexicalStructure.html#identifier) **)** > *setter名称* → **(** [*标识符*](LexicalStructure.html#identifier) **)**
> *getter-setter关键字(Keyword)块* → **{** [*getter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#getter_keyword_clause) [*setter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#setter_keyword_clause) _可选_ **}** > *getter-setter关键字(Keyword)块* → **{** [*getter关键字(Keyword)子句*](../chapter3/05_Declarations.html#getter_keyword_clause) [*setter关键字(Keyword)子句*](../chapter3/05_Declarations.html#setter_keyword_clause) _可选_ **}**
> *getter-setter关键字(Keyword)块* → **{** [*setter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#setter_keyword_clause) [*getter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#getter_keyword_clause) **}** > *getter-setter关键字(Keyword)块* → **{** [*setter关键字(Keyword)子句*](../chapter3/05_Declarations.html#setter_keyword_clause) [*getter关键字(Keyword)子句*](../chapter3/05_Declarations.html#getter_keyword_clause) **}**
> *getter关键字(Keyword)子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **get** > *getter关键字(Keyword)子句* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ **get**
> *setter关键字(Keyword)子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **set** > *setter关键字(Keyword)子句* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ **set**
> *willSet-didSet代码块* → **{** [*willSet子句*](..\chapter3\05_Declarations.html#willSet_clause) [*didSet子句*](..\chapter3\05_Declarations.html#didSet_clause) _可选_ **}** > *willSet-didSet代码块* → **{** [*willSet子句*](../chapter3/05_Declarations.html#willSet_clause) [*didSet子句*](../chapter3/05_Declarations.html#didSet_clause) _可选_ **}**
> *willSet-didSet代码块* → **{** [*didSet子句*](..\chapter3\05_Declarations.html#didSet_clause) [*willSet子句*](..\chapter3\05_Declarations.html#willSet_clause) **}** > *willSet-didSet代码块* → **{** [*didSet子句*](../chapter3/05_Declarations.html#didSet_clause) [*willSet子句*](../chapter3/05_Declarations.html#willSet_clause) **}**
> *willSet子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **willSet** [*setter名称*](..\chapter3\05_Declarations.html#setter_name) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block) > *willSet子句* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ **willSet** [*setter名称*](../chapter3/05_Declarations.html#setter_name) _可选_ [*代码块*](../chapter3/05_Declarations.html#code_block)
> *didSet子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **didSet** [*setter名称*](..\chapter3\05_Declarations.html#setter_name) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block) > *didSet子句* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ **didSet** [*setter名称*](../chapter3/05_Declarations.html#setter_name) _可选_ [*代码块*](../chapter3/05_Declarations.html#code_block)
<a name="type_alias_declaration"></a> <a name="type_alias_declaration"></a>
##类型的别名声明 ##类型的别名声明
@ -260,13 +264,13 @@ setter的名字和圆括号内的语句是可选的。如果写了一个setter
当声明一个类型的别名后,可以在程序的任何地方使用别*名(name)*来代替*已存在的类型(existing type)*。已存在的类型可以是已经被命名的类型或者是混合类型。类型的别名不产生新的类型,它只是简单的和已存在的类型做名称替换。 当声明一个类型的别名后,可以在程序的任何地方使用别*名(name)*来代替*已存在的类型(existing type)*。已存在的类型可以是已经被命名的类型或者是混合类型。类型的别名不产生新的类型,它只是简单的和已存在的类型做名称替换。
查看更多[协议关联类型声明(Protocol Associated Type Declaration)](TODO). 查看更多[协议关联类型声明(Protocol Associated Type Declaration)](TODO).
<a name="grammer_of_a_type_alias_declaration"></a> <a name="grammer_of_a_type_alias_declaration"></a>
> 类型别名声明语法 > 类型别名声明语法
> *类型别名声明* → [*类型别名头(Head)*](..\chapter3\05_Declarations.html#typealias_head) [*类型别名赋值*](..\chapter3\05_Declarations.html#typealias_assignment) > *类型别名声明* → [*类型别名头(Head)*](../chapter3/05_Declarations.html#typealias_head) [*类型别名赋值*](../chapter3/05_Declarations.html#typealias_assignment)
> *类型别名头(Head)* → [*属性列表*](todo) _可选_ [*访问级别修饰符*]((TODO) _可选_ **typealias** [*类型别名名称*](..\chapter3\05_Declarations.html#typealias_name) > *类型别名头(Head)* → [*属性列表*](todo) _可选_ [*访问级别修饰符*]((TODO) _可选_ **typealias** [*类型别名名称*](../chapter3/05_Declarations.html#typealias_name)
> *类型别名名称* → [*标识符*](LexicalStructure.html#identifier) > *类型别名名称* → [*标识符*](LexicalStructure.html#identifier)
> *类型别名赋值* → **=** [*类型*](..\chapter3\03_Types.html#type) > *类型别名赋值* → **=** [*类型*](../chapter3/03_Types.html#type)
<a name="function_declaration"></a> <a name="function_declaration"></a>
##函数声明 ##函数声明
@ -289,7 +293,7 @@ setter的名字和圆括号内的语句是可选的。如果写了一个setter
函数可以使用元组类型作为返回值来返回多个变量。 函数可以使用元组类型作为返回值来返回多个变量。
函数定义可以出现在另一个函数声明内。这种函数被称作nested函数。更多关于*嵌套函数(Nested Functions)*的讨论,参见[嵌套函数(Nested Functions)](TODO)。 函数定义可以出现在另一个函数声明内。这种函数被称作nested函数。更多关于*嵌套函数(Nested Functions)*的讨论,参见[嵌套函数(Nested Functions)](TODO)。
<a name="parameter_names"></a> <a name="parameter_names"></a>
###参数名 ###参数名
@ -301,7 +305,7 @@ setter的名字和圆括号内的语句是可选的。如果写了一个setter
一个参数有一个内部名称,这个内部名称可以在函数体内被使用。同样也可以作为外部名称,当调用方法时这个外部名称被作为实参的标签来使用。默认情况下,第一个参数的外部名称省略不写,第二个和其之后的参数使用它们的内部名称作为它们的外部名称。 一个参数有一个内部名称,这个内部名称可以在函数体内被使用。同样也可以作为外部名称,当调用方法时这个外部名称被作为实参的标签来使用。默认情况下,第一个参数的外部名称省略不写,第二个和其之后的参数使用它们的内部名称作为它们的外部名称。
```swift ```swift
func f(x: Int, y: Int) -> Int{ return x + y} func f(x: Int, y: Int) -> Int{ return x + y}
f(1, y: 2) // y是有标记的x没有 f(1, y: 2) // y是有标记的x没有
``` ```
@ -309,17 +313,17 @@ f(1, y: 2) // y是有标记的x没有
> `external parameter name` `local parameter name`: `parameter type` > `external parameter name` `local parameter name`: `parameter type`
> _ `local parameter name`: `parameter type` > _ `local parameter name`: `parameter type`
在内部参数名前的名称赋予这个参数一个外部名称,这个名称可以和内部参数的名称不同。外部参数名在函数被调用时必须被使用。对应的参数在方法或函数被调用时必须有外部名 。 在内部参数名前的名称赋予这个参数一个外部名称,这个名称可以和内部参数的名称不同。外部参数名在函数被调用时必须被使用。对应的参数在方法或函数被调用时必须有外部名 。
内部参数名前的强调字符下划线(_)使参数在函数被调用时没有名称。在函数或方法调用时,与其对应的语句必须没有名字。 内部参数名前的强调字符下划线(_)使参数在函数被调用时没有名称。在函数或方法调用时,与其对应的语句必须没有名字。
```swift ```swift
func f(x x: Int, withY y: Int, _z: Int) -> Int{ func f(x x: Int, withY y: Int, _z: Int) -> Int{
return x + y + z } return x + y + z }
f(x: 1, withY: 2, 3) // x和y是有标记的z没有 f(x: 1, withY: 2, 3) // x和y是有标记的z没有
``` ```
<a name="special_kinds_of_parameters"></a> <a name="special_kinds_of_parameters"></a>
###特殊类型的参数 ###特殊类型的参数
@ -333,13 +337,13 @@ f(x: 1, withY: 2, 3) // x和y是有标记的z没有
一个以基础类型名的参数,如果紧跟着三个点(`...`),被理解为是可变参数。一个函数至多可以拥有一个可变参数,且必须是最后一个参数。可变参数被作为该基本类型名的数组来看待。举例来讲,可变参数`Int...`被看做是`[Int]`。查看可变参数的使用例子,详见[可变参数(Variadic Parameters)](TODO)一节。 一个以基础类型名的参数,如果紧跟着三个点(`...`),被理解为是可变参数。一个函数至多可以拥有一个可变参数,且必须是最后一个参数。可变参数被作为该基本类型名的数组来看待。举例来讲,可变参数`Int...`被看做是`[Int]`。查看可变参数的使用例子,详见[可变参数(Variadic Parameters)](TODO)一节。
在参数的类型后面有一个以等号(`=`)连接的表达式,这样的参数被看做有着给定表达式的初始值。当函数被调用时,给定的表达式被求值。如果参数在函数调用时被省略了,就会使用初始值。 在参数的类型后面有一个以等号(`=`)连接的表达式,这样的参数被看做有着给定表达式的初始值。当函数被调用时,给定的表达式被求值。如果参数在函数调用时被省略了,就会使用初始值。
```swift ```swift
func f(x: Int = 42) -> Int { return x} func f(x: Int = 42) -> Int { return x}
f() // 有效的,使用默认值 f() // 有效的,使用默认值
f(7) // 有效的,提供了值,没有提供值的名称 f(7) // 有效的,提供了值,没有提供值的名称
f(x: 7) //无效的,值和值的名称都提供了 f(x: 7) //无效的,值和值的名称都提供了
``` ```
<a name="special_kinds_of_methods"></a> <a name="special_kinds_of_methods"></a>
###特殊方法 ###特殊方法
@ -347,9 +351,9 @@ f(x: 7) //无效的,值和值的名称都提供了
枚举或结构体的方法来修改`self`属性,必须以`mutating`声明修饰符标记。 枚举或结构体的方法来修改`self`属性,必须以`mutating`声明修饰符标记。
子类方法重写超类中的方法必须以`override`声明修饰符标记。重写一个方法不使用`override`修饰符,或者使用了`override`修饰符却并没有重写超类方法都会产生一个编译时错误。 子类方法重写超类中的方法必须以`override`声明修饰符标记。重写一个方法不使用`override`修饰符,或者使用了`override`修饰符却并没有重写超类方法都会产生一个编译时错误。
枚举或者结构体中的类型方法而不是实例方法,要以`static`声明修饰符标记,而对于类中的类型方法,要使用`class`声明修饰符标记。 枚举或者结构体中的类型方法而不是实例方法,要以`static`声明修饰符标记,而对于类中的类型方法,要使用`class`声明修饰符标记。
<a name="curried_functions"></a> <a name="curried_functions"></a>
###柯里化函数(Curried Functions) ###柯里化函数(Curried Functions)
@ -383,7 +387,7 @@ func addTwoIntsCurried(a a: Int)(b: Int) -> Int {
return a + b return a + b
} }
func addTwoIntsCurried(a a: Int) -> (Int -> Int) func addTwoIntsCurried(a a: Int) -> (Int -> Int)
{ {
func addTheOtherInt(b: Int) -> Int { func addTheOtherInt(b: Int) -> Int {
return a + b return a + b
@ -413,64 +417,64 @@ let plusOne = addTwoIntsCurried(a: 1)
```swift ```swift
plusOne(10) plusOne(10)
// 返回值为11 // 返回值为11
``` ```
<a name="throwing_functions_and_methods"></a> <a name="throwing_functions_and_methods"></a>
###抛出异常函数和抛出异常方法(Throwing Functions and Methods) ###抛出异常函数和抛出异常方法(Throwing Functions and Methods)
可以抛出一个错误的函数或方法必需使用`throws`关键字标记。这些函数和方法被称为*抛出异常函数(throwing functions)*和*抛出异常方法(throwing methods)*。它们有着下面的形式: 可以抛出一个错误的函数或方法必需使用`throws`关键字标记。这些函数和方法被称为*抛出异常函数(throwing functions)*和*抛出异常方法(throwing methods)*。它们有着下面的形式:
> func `function name`(`parameters`) throws -> > func `function name`(`parameters`) throws ->
> `return type` { > `return type` {
> `statements` > `statements`
> } > }
调用一个抛出异常函数或抛出异常方法必需用一个`try`或者`try!`表达式来封装(也就是说,在一个范围内使用一个`try`或者`try!`运算符)。 调用一个抛出异常函数或抛出异常方法必需用一个`try`或者`try!`表达式来封装(也就是说,在一个范围内使用一个`try`或者`try!`运算符)。
`throws`关键字是函数的类型的一部分,不抛出异常的函数是抛出异常函数的一个子类型。所以,可以在使用抛出异常函数的地方使用不抛出异常函数。对于柯里化函数,`throws`关键字仅运用于最内层的函数。 `throws`关键字是函数的类型的一部分,不抛出异常的函数是抛出异常函数的一个子类型。所以,可以在使用抛出异常函数的地方使用不抛出异常函数。对于柯里化函数,`throws`关键字仅运用于最内层的函数。
不能重写一个仅基于是否能抛出错误的函数。也就是说,可以重载一个基于函数*参数(parameter)*能否抛出一个错误的函数。 不能重写一个仅基于是否能抛出错误的函数。也就是说,可以重载一个基于函数*参数(parameter)*能否抛出一个错误的函数。
一个抛出异常的方法不能重写一个不能抛出异常的方法,而且一个异常抛出方法不能满足一个协议对于不抛出异常方法的需求。也就是说,一个不抛出异常的方法可以重写一个抛出异常的方法,而且一个不抛出异常的方法可以满足一个协议对于抛出异常的需求。 一个抛出异常的方法不能重写一个不能抛出异常的方法,而且一个异常抛出方法不能满足一个协议对于不抛出异常方法的需求。也就是说,一个不抛出异常的方法可以重写一个抛出异常的方法,而且一个不抛出异常的方法可以满足一个协议对于抛出异常的需求。
<a name="rethrowing_functions_and_methods"></a> <a name="rethrowing_functions_and_methods"></a>
###重抛出异常函数和重抛出异常方法(Rethrowing Functions and Methods) ###重抛出异常函数和重抛出异常方法(Rethrowing Functions and Methods)
一个函数或方法可以使用`rethrows`关键字来声明,从而表明仅当这个函数或方法的一个函数参数抛出错误时这个函数或方法才抛出错误。这些函数和方法被称为*重抛出异常函数(rethrowing functions)*和*重抛出异常方法(rethrowing methods)*。重抛出异常函数或方法必需有至少一个抛出异常函数参数。 一个函数或方法可以使用`rethrows`关键字来声明,从而表明仅当这个函数或方法的一个函数参数抛出错误时这个函数或方法才抛出错误。这些函数和方法被称为*重抛出异常函数(rethrowing functions)*和*重抛出异常方法(rethrowing methods)*。重抛出异常函数或方法必需有至少一个抛出异常函数参数。
``` ```
func functionWithCallback(callback: () throws -> Int) rethrows { func functionWithCallback(callback: () throws -> Int) rethrows {
try callback() try callback()
} }
``` ```
一个抛出异常函数方法不能重写一个重抛出异常函数方法,一个抛出异常方法不能满足一个协议对于重抛出异常方法的需求。也就是说,一个重抛出异常方法可以重写一个抛出异常方法,而且一个重抛出异常方法可以满足一个协议对于抛出异常方法的需求。 一个抛出异常函数方法不能重写一个重抛出异常函数方法,一个抛出异常方法不能满足一个协议对于重抛出异常方法的需求。也就是说,一个重抛出异常方法可以重写一个抛出异常方法,而且一个重抛出异常方法可以满足一个协议对于抛出异常方法的需求。
<a name="grammer_of_a_function_declaration"></a> <a name="grammer_of_a_function_declaration"></a>
> 函数声明语法 > 函数声明语法
> *函数声明* → [*函数头*](..\chapter3\05_Declarations.html#function_head) [*函数名*](..\chapter3\05_Declarations.html#function_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*函数签名(Signature)*](..\chapter3\05_Declarations.html#function_signature) [*函数体*](..\chapter3\05_Declarations.html#function_body) > *函数声明* → [*函数头*](../chapter3/05_Declarations.html#function_head) [*函数名*](../chapter3/05_Declarations.html#function_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*函数签名(Signature)*](../chapter3/05_Declarations.html#function_signature) [*函数体*](../chapter3/05_Declarations.html#function_body)
> *函数头* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修饰符(Specifiers)列表*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **func** > *函数头* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*声明修饰符(Specifiers)列表*](../chapter3/05_Declarations.html#declaration_specifiers) _可选_ **func**
> *函数名* → [*标识符*](LexicalStructure.html#identifier) | [*运算符*](LexicalStructure.html#operator) > *函数名* → [*标识符*](LexicalStructure.html#identifier) | [*运算符*](LexicalStructure.html#operator)
> *函数签名(signature)* → [*parameter-clauses*](..\chapter3\05_Declarations.html#parameter_clauses) **throws** [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ > *函数签名(signature)* → [*parameter-clauses*](../chapter3/05_Declarations.html#parameter_clauses) **throws** [*函数结果*](../chapter3/05_Declarations.html#function_result) _可选_
> *函数签名(signature)* → [*parameter-clauses*](..\chapter3\05_Declarations.html#parameter_clauses) **rethrows** [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ > *函数签名(signature)* → [*parameter-clauses*](../chapter3/05_Declarations.html#parameter_clauses) **rethrows** [*函数结果*](../chapter3/05_Declarations.html#function_result) _可选_
> *函数结果* → **->** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type) > *函数结果* → **->** [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*类型*](../chapter3/03_Types.html#type)
> *函数体* → [*代码块*](..\chapter3\05_Declarations.html#code_block) > *函数体* → [*代码块*](../chapter3/05_Declarations.html#code_block)
> *parameter-clauses* → [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*parameter-clauses*](..\chapter3\05_Declarations.html#parameter_clauses) _可选_ > *parameter-clauses* → [*参数子句*](../chapter3/05_Declarations.html#parameter_clause) [*parameter-clauses*](../chapter3/05_Declarations.html#parameter_clauses) _可选_
> *参数子句* → **(** **)** | **(** [*参数列表*](..\chapter3\05_Declarations.html#parameter_list) **...** _可选_ **)** > *参数子句* → **(** **)** | **(** [*参数列表*](../chapter3/05_Declarations.html#parameter_list) **...** _可选_ **)**
> *参数列表* → [*参数*](..\chapter3\05_Declarations.html#parameter) | [*参数*](..\chapter3\05_Declarations.html#parameter) **,** [*参数列表*](..\chapter3\05_Declarations.html#parameter_list) > *参数列表* → [*参数*](../chapter3/05_Declarations.html#parameter) | [*参数*](../chapter3/05_Declarations.html#parameter) **,** [*参数列表*](../chapter3/05_Declarations.html#parameter_list)
> *参数* → **inout** _可选_ **let** _可选_ [*外部参数名*](..\chapter3\05_Declarations.html#parameter_name)_可选_ [*内部参数名*](..\chapter3\05_Declarations.html#local_parameter_name) [*类型标注*](..\chapter3\03_Types.html#type_annotation) [*默认参数子句*](..\chapter3\05_Declarations.html#default_argument_clause) _可选_ > *参数* → **inout** _可选_ **let** _可选_ [*外部参数名*](../chapter3/05_Declarations.html#parameter_name)_可选_ [*内部参数名*](../chapter3/05_Declarations.html#local_parameter_name) [*类型标注*](../chapter3/03_Types.html#type_annotation) [*默认参数子句*](../chapter3/05_Declarations.html#default_argument_clause) _可选_
> *参数* → **inout** _可选_ **var** [*外部参数名*](..\chapter3\05_Declarations.html#parameter_name) [*内部参数名*](..\chapter3\05_Declarations.html#local_parameter_name) [*类型标注*](..\chapter3\03_Types.html#type_annotation) [*默认参数子句*](..\chapter3\05_Declarations.html#default_argument_clause) _可选_ > *参数* → **inout** _可选_ **var** [*外部参数名*](../chapter3/05_Declarations.html#parameter_name) [*内部参数名*](../chapter3/05_Declarations.html#local_parameter_name) [*类型标注*](../chapter3/03_Types.html#type_annotation) [*默认参数子句*](../chapter3/05_Declarations.html#default_argument_clause) _可选_
> *参数* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type) > *参数* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*类型*](../chapter3/03_Types.html#type)
> *参数名* → [*标识符*](LexicalStructure.html#identifier) | **_** > *参数名* → [*标识符*](LexicalStructure.html#identifier) | **_**
> *内部参数名* → [*标识符*](LexicalStructure.html#identifier) | **_** > *内部参数名* → [*标识符*](LexicalStructure.html#identifier) | **_**
> *默认参数子句* → **=** [*表达式*](..\chapter3\04_Expressions.html#expression) > *默认参数子句* → **=** [*表达式*](../chapter3/04_Expressions.html#expression)
<a name="enumeration_declaration"></a> <a name="enumeration_declaration"></a>
##枚举声明 ##枚举声明
在程序里使用*枚举声明(enumeration)*来引入一个枚举类型。 在程序里使用*枚举声明(enumeration)*来引入一个枚举类型。
枚举声明有两种基本的形式,使用关键字`enum`来声明。枚举声明体使用从零开始的变量——叫做*枚举事件(enumeration cases)*,和任意数量的声明,包括计算型属性,实例方法,类型方法,构造器,类型别名,甚至其他枚举,结构体,和类。枚举声明不能包含析构器或者协议声明。 枚举声明有两种基本的形式,使用关键字`enum`来声明。枚举声明体使用从零开始的变量——叫做*枚举事件(enumeration cases)*,和任意数量的声明,包括计算型属性,实例方法,类型方法,构造器,类型别名,甚至其他枚举,结构体,和类。枚举声明不能包含析构器或者协议声明。
枚举类型可以采用任何数量的协议,但是这些协议不能从类,结构体和其他的枚举继承。 枚举类型可以采用任何数量的协议,但是这些协议不能从类,结构体和其他的枚举继承。
不像类或者结构体。枚举类型并不提供隐式的初始构造器,所有构造器必须显式的声明。构造器可以委托枚举中的其他构造器,但是构造过程仅当构造器将一个枚事件指定给`self`才全部完成。 不像类或者结构体。枚举类型并不提供隐式的初始构造器,所有构造器必须显式的声明。构造器可以委托枚举中的其他构造器,但是构造过程仅当构造器将一个枚事件指定给`self`才全部完成。
@ -479,7 +483,7 @@ plusOne(10)
更多关于值类型的信息,参见结构体和枚举都是[值类型(Structures and Enumerations Are Value Types)](TODO)一节。 更多关于值类型的信息,参见结构体和枚举都是[值类型(Structures and Enumerations Are Value Types)](TODO)一节。
可以扩展枚举类型,正如在[扩展声明(Extension Declaration)](TODO)中讨论的一样。 可以扩展枚举类型,正如在[扩展声明(Extension Declaration)](TODO)中讨论的一样。
<a name="enumerations_with_cases_of_any_type"></a> <a name="enumerations_with_cases_of_any_type"></a>
###任意事件类型的枚举 ###任意事件类型的枚举
@ -494,21 +498,21 @@ plusOne(10)
这种形式中,每一个事件块由关键字`case`开始,后面紧接着一个或多个以逗号分隔的枚举事件。每一个事件名必须是独一无二的。每一个事件也可以指定它所存储的指定类型的值,这些类型在*关联值类型(associated values types)*的元组里被指定,立即书写在事件 这种形式中,每一个事件块由关键字`case`开始,后面紧接着一个或多个以逗号分隔的枚举事件。每一个事件名必须是独一无二的。每一个事件也可以指定它所存储的指定类型的值,这些类型在*关联值类型(associated values types)*的元组里被指定,立即书写在事件
名后。获得更多关于关联值类型的信息和例子,请查看[关联值(Associated Values)](TODO)一节。 名后。获得更多关于关联值类型的信息和例子,请查看[关联值(Associated Values)](TODO)一节。
枚举有一个递归结构,就是说,枚举有着枚举类型自身实例的关联值的事件。然而,枚举类型的实例有值语义,意味着它们在内存中有着固定的位置。为了支持递归,编译器必需插入一个间接层。 枚举有一个递归结构,就是说,枚举有着枚举类型自身实例的关联值的事件。然而,枚举类型的实例有值语义,意味着它们在内存中有着固定的位置。为了支持递归,编译器必需插入一个间接层。
为间接使用特殊的枚举事件,使用`indirect`声明修饰符标记。 为间接使用特殊的枚举事件,使用`indirect`声明修饰符标记。
> enum Tree<T> { > enum Tree<T> {
> case Empty > case Empty
> indirect case Node(value: T, left: Tree, right:Tree) > indirect case Node(value: T, left: Tree, right:Tree)
> } > }
为了间接的使用一个枚举的所有事件,使用`indirect`修饰符标记整个枚举-当枚举有许多事件且每个事件都需要使用`indirect`修饰符标记的时候这将非常便利。 为了间接的使用一个枚举的所有事件,使用`indirect`修饰符标记整个枚举-当枚举有许多事件且每个事件都需要使用`indirect`修饰符标记的时候这将非常便利。
一个被`indirect`修饰符标记的枚举事件必需有一个关联值。一个使用`indirect`修饰符标记的枚举包含有着关联值的事件和没有关联值的事件的混合。就是说,它不能包含任何也使用`indirect`修饰符标记的事件。 一个被`indirect`修饰符标记的枚举事件必需有一个关联值。一个使用`indirect`修饰符标记的枚举包含有着关联值的事件和没有关联值的事件的混合。就是说,它不能包含任何也使用`indirect`修饰符标记的事件。
<a name="enumerations_with_cases_of_a_raw-value_type"></a> <a name="enumerations_with_cases_of_a_raw-value_type"></a>
###使用原始值类型事件的枚举(Enumerations with Cases of a Raw-Value Type) ###使用原始值类型事件的枚举(Enumerations with Cases of a Raw-Value Type)
@ -519,8 +523,8 @@ plusOne(10)
> case `enumeration case 2` = `raw value 2` > case `enumeration case 2` = `raw value 2`
> } > }
在这种形式中,每一个事件块由`case`关键字开始,后面紧接着一个或多个以逗号分隔的枚举事件。和第一种形式的枚举事件不同,这种形式的枚举事件包含一个同类型的基础值,叫做*原始值(raw value)*。这些值的类型在*原始值类型(raw-value type)*中被指定,必须表示一个整数,浮点数,字符串,或者一个字符。特别是*原始值类型(raw-value type)*必需遵守`Equatable`类型的协议和下列形式中的一种字面量构造协议(literal-convertible protocols):整型字面量有`IntergerLiteralConvertible`,浮点行字面量有`FloatingPointLiteralConvertible`,包含任意数量字符的字符串型字面量有`StringLiteralConvertible`,仅包含一个单一字符的字符串型字面量有`ExtendedGraphemeClusterLiteralConvertible`。每一个事件必须有唯一的名字,必须有一个唯一的初始值。 在这种形式中,每一个事件块由`case`关键字开始,后面紧接着一个或多个以逗号分隔的枚举事件。和第一种形式的枚举事件不同,这种形式的枚举事件包含一个同类型的基础值,叫做*原始值(raw value)*。这些值的类型在*原始值类型(raw-value type)*中被指定,必须表示一个整数,浮点数,字符串,或者一个字符。特别是*原始值类型(raw-value type)*必需遵守`Equatable`类型的协议和下列形式中的一种字面量构造协议(literal-convertible protocols):整型字面量有`IntergerLiteralConvertible`,浮点行字面量有`FloatingPointLiteralConvertible`,包含任意数量字符的字符串型字面量有`StringLiteralConvertible`,仅包含一个单一字符的字符串型字面量有`ExtendedGraphemeClusterLiteralConvertible`。每一个事件必须有唯一的名字,必须有一个唯一的初始值。
如果初始值类型被指定为`Int`,则不必为事件显式的指定值,它们会隐式的被标为值`0,1,2`等。每一个没有被赋值的`Int`类型时间会隐式的赋予一个初始值,它们是自动递增的。 如果初始值类型被指定为`Int`,则不必为事件显式的指定值,它们会隐式的被标为值`0,1,2`等。每一个没有被赋值的`Int`类型时间会隐式的赋予一个初始值,它们是自动递增的。
```Swift ```Swift
@ -529,44 +533,44 @@ num ExampleEnum: Int {
} }
``` ```
在上面的例子中,`ExampleEnum.A`的值是`0``ExampleEnum.B`的值是`1`。因为`ExampleEnum.C`的值被显式的设定为`5`,因此`ExampleEnum.D`的值会自动增长为`6` 在上面的例子中,`ExampleEnum.A`的值是`0``ExampleEnum.B`的值是`1`。因为`ExampleEnum.C`的值被显式的设定为`5`,因此`ExampleEnum.D`的值会自动增长为`6`
如果原始值类型被指定为`String`类型,你不用明确的为事件指定值,每一个没有指定的事件会隐式地用与事件名字相同的字符串指定。 如果原始值类型被指定为`String`类型,你不用明确的为事件指定值,每一个没有指定的事件会隐式地用与事件名字相同的字符串指定。
> enum WeekendDay: String { > enum WeekendDay: String {
> case Saturday, Sunday > case Saturday, Sunday
> } > }
在上面这个例子中,`WeekendDay.Saturday`的原始值是`"Saturday"`,`WeekendDay.Sunday`的原始值是`"Sunday"` 在上面这个例子中,`WeekendDay.Saturday`的原始值是`"Saturday"`,`WeekendDay.Sunday`的原始值是`"Sunday"`
拥有多种事件的原始值类型的枚举含蓄地遵循定义在Swift标准库中的`RawRepresentable`协议。所以,它们拥有一个原始值(`rawValue`)属性和一个有着`init?(rawValue: RawValue)`签名的可失败构造器(a failable initializer)。可以使用原始值属性去取的枚举事件的原始值,就像在`ExampleEnum.B.rawValue`中一样。如果有一个事件符合,也可以使用原始值去找到一个符合的事件,通过调用枚举的可失败构造器,如`ExampleEnum(rawValue: 5)`,这个可失败构造器返回一个可选的事件。想得到更多的信息和关于原始值类型查看更多信息和获取初始值类型事件的信息,参阅初始值[原始值(Raw Values)](TODO)。 拥有多种事件的原始值类型的枚举含蓄地遵循定义在Swift标准库中的`RawRepresentable`协议。所以,它们拥有一个原始值(`rawValue`)属性和一个有着`init?(rawValue: RawValue)`签名的可失败构造器(a failable initializer)。可以使用原始值属性去取的枚举事件的原始值,就像在`ExampleEnum.B.rawValue`中一样。如果有一个事件符合,也可以使用原始值去找到一个符合的事件,通过调用枚举的可失败构造器,如`ExampleEnum(rawValue: 5)`,这个可失败构造器返回一个可选的事件。想得到更多的信息和关于原始值类型查看更多信息和获取初始值类型事件的信息,参阅初始值[原始值(Raw Values)](TODO)。
<a name="accessing_enumeration_cases"></a> <a name="accessing_enumeration_cases"></a>
###获得枚举事件 ###获得枚举事件
使用点(.)来引用枚举类型的事件,如`EnumerationType.EnumerationCase`。当枚举类型可以上下文推断出时,可以省略它(.仍然需要),参照枚举语法[(Enumeration Syntax)](TODO)和[显式成员表达(Implicit Member Expression)](TODO)。 使用点(.)来引用枚举类型的事件,如`EnumerationType.EnumerationCase`。当枚举类型可以上下文推断出时,可以省略它(.仍然需要),参照枚举语法[(Enumeration Syntax)](TODO)和[显式成员表达(Implicit Member Expression)](TODO)。
使用`switch`语句来检验枚举事件的值,正如使用[switch语句匹配枚举值Matching Enumeration Values with a Switch Statement)](TODO)一节描述的那样。枚举类型是模式匹配(pattern-matched)的,和其相反的是`switch`语句case块中枚举事件匹配在[枚举事件类型(Enumeration Case Pattern)](TODO)中有描述。 使用`switch`语句来检验枚举事件的值,正如使用[switch语句匹配枚举值Matching Enumeration Values with a Switch Statement)](TODO)一节描述的那样。枚举类型是模式匹配(pattern-matched)的,和其相反的是`switch`语句case块中枚举事件匹配在[枚举事件类型(Enumeration Case Pattern)](TODO)中有描述。
<a name="grammer_of_an_enumeration_declaration"></a> <a name="grammer_of_an_enumeration_declaration"></a>
> 枚举声明语法 > 枚举声明语法
> *枚举声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*访问级别修饰符*](TODO) _可选_ [*联合式枚举*](TODO) > *枚举声明* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*访问级别修饰符*](TODO) _可选_ [*联合式枚举*](TODO)
> *枚举声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*访问级别修饰符*](TODO) _可选_ [*原始值式枚举*](..\chapter3\05_Declarations.html#raw_value_style_enum) > *枚举声明* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*访问级别修饰符*](TODO) _可选_ [*原始值式枚举*](../chapter3/05_Declarations.html#raw_value_style_enum)
> *联合式枚举* → **indirect** _可选_ **enum** [*枚举名*](..\chapter3\05_Declarations.html#enum_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [类型继承子句](TODO)_可选_ **{** [*union-style-enum-members*](..\chapter3\05_Declarations.html#union_style_enum_members) _可选_ **}** > *联合式枚举* → **indirect** _可选_ **enum** [*枚举名*](../chapter3/05_Declarations.html#enum_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [类型继承子句](TODO)_可选_ **{** [*union-style-enum-members*](../chapter3/05_Declarations.html#union_style_enum_members) _可选_ **}**
> *union-style-enum-members* → [*union-style-enum-member*](..\chapter3\05_Declarations.html#union_style_enum_member) [*union-style-enum-members*](..\chapter3\05_Declarations.html#union_style_enum_members) _可选_ > *union-style-enum-members* → [*union-style-enum-member*](../chapter3/05_Declarations.html#union_style_enum_member) [*union-style-enum-members*](../chapter3/05_Declarations.html#union_style_enum_members) _可选_
> *union-style-enum-member* → [*声明*](..\chapter3\05_Declarations.html#declaration) | [*联合式(Union Style)的枚举case子句*](..\chapter3\05_Declarations.html#union_style_enum_case_clause) > *union-style-enum-member* → [*声明*](../chapter3/05_Declarations.html#declaration) | [*联合式(Union Style)的枚举case子句*](../chapter3/05_Declarations.html#union_style_enum_case_clause)
> *联合式(Union Style)的枚举case子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **indirect** _可选_ **case** [*联合式(Union Style)的枚举case列表*](..\chapter3\05_Declarations.html#union_style_enum_case_list) > *联合式(Union Style)的枚举case子句* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ **indirect** _可选_ **case** [*联合式(Union Style)的枚举case列表*](../chapter3/05_Declarations.html#union_style_enum_case_list)
> *联合式(Union Style)的枚举case列表* → [*联合式(Union Style)的case*](..\chapter3\05_Declarations.html#union_style_enum_case) | [*联合式(Union Style)的case*](..\chapter3\05_Declarations.html#union_style_enum_case) **,** [*联合式(Union Style)的枚举case列表*](..\chapter3\05_Declarations.html#union_style_enum_case_list) > *联合式(Union Style)的枚举case列表* → [*联合式(Union Style)的case*](../chapter3/05_Declarations.html#union_style_enum_case) | [*联合式(Union Style)的case*](../chapter3/05_Declarations.html#union_style_enum_case) **,** [*联合式(Union Style)的枚举case列表*](../chapter3/05_Declarations.html#union_style_enum_case_list)
> *联合式(Union Style)的case* → [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*元组类型*](..\chapter3\03_Types.html#tuple_type) _可选_ > *联合式(Union Style)的case* → [*枚举的case名*](../chapter3/05_Declarations.html#enum_case_name) [*元组类型*](../chapter3/03_Types.html#tuple_type) _可选_
> *枚举名* → [*标识符*](LexicalStructure.html#identifier) > *枚举名* → [*标识符*](LexicalStructure.html#identifier)
> *枚举的case名* → [*标识符*](LexicalStructure.html#identifier) > *枚举的case名* → [*标识符*](LexicalStructure.html#identifier)
> *原始值式枚举* → **enum** [*枚举名*](..\chapter3\05_Declarations.html#enum_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承子句*](TODO) **{** [*原始值式枚举成员列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_members) **}** > *原始值式枚举* → **enum** [*枚举名*](../chapter3/05_Declarations.html#enum_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承子句*](TODO) **{** [*原始值式枚举成员列表*](../chapter3/05_Declarations.html#raw_value_style_enum_members) **}**
> *原始值式枚举成员列表* → [*原始值式枚举成员*](..\chapter3\05_Declarations.html#raw_value_style_enum_member) [*原始值式枚举成员列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_members) _可选_ > *原始值式枚举成员列表* → [*原始值式枚举成员*](../chapter3/05_Declarations.html#raw_value_style_enum_member) [*原始值式枚举成员列表*](../chapter3/05_Declarations.html#raw_value_style_enum_members) _可选_
> *原始值式枚举成员* → [*声明*](..\chapter3\05_Declarations.html#declaration) | [*原始值式枚举case子句*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_clause) > *原始值式枚举成员* → [*声明*](../chapter3/05_Declarations.html#declaration) | [*原始值式枚举case子句*](../chapter3/05_Declarations.html#raw_value_style_enum_case_clause)
> *原始值式枚举case子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **case** [*原始值式枚举case列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_list) > *原始值式枚举case子句* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ **case** [*原始值式枚举case列表*](../chapter3/05_Declarations.html#raw_value_style_enum_case_list)
> *原始值式枚举case列表* → [*原始值式枚举case*](..\chapter3\05_Declarations.html#raw_value_style_enum_case) | [*原始值式枚举case*](..\chapter3\05_Declarations.html#raw_value_style_enum_case) **,** [*原始值式枚举case列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_list) > *原始值式枚举case列表* → [*原始值式枚举case*](../chapter3/05_Declarations.html#raw_value_style_enum_case) | [*原始值式枚举case*](../chapter3/05_Declarations.html#raw_value_style_enum_case) **,** [*原始值式枚举case列表*](../chapter3/05_Declarations.html#raw_value_style_enum_case_list)
> *原始值式枚举case* → [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*原始值赋值*](..\chapter3\05_Declarations.html#raw_value_assignment) _可选_ > *原始值式枚举case* → [*枚举的case名*](../chapter3/05_Declarations.html#enum_case_name) [*原始值赋值*](../chapter3/05_Declarations.html#raw_value_assignment) _可选_
> *原始值赋值* → **=** [*原始值字面量*](TODO) > *原始值赋值* → **=** [*原始值字面量*](TODO)
> *原始值字面量* → [数字型字面量](TODO)|[字符串型字面量](TODO)|[布尔型字面量](TODO) > *原始值字面量* → [数字型字面量](TODO)|[字符串型字面量](TODO)|[布尔型字面量](TODO)
<a name="structure_declaration"></a> <a name="structure_declaration"></a>
@ -598,12 +602,12 @@ num ExampleEnum: Int {
[结构体和枚举是值类型(Structures and Enumerations Are Value Types)](TODO)一节。 [结构体和枚举是值类型(Structures and Enumerations Are Value Types)](TODO)一节。
可以使用扩展声明来扩展结构体类型的行为,参见[扩展声明(Extension Declaration)](TODO)。 可以使用扩展声明来扩展结构体类型的行为,参见[扩展声明(Extension Declaration)](TODO)。
<a name="grammer_of_a_structure_declaration"></a> <a name="grammer_of_a_structure_declaration"></a>
> 结构体声明语法 > 结构体声明语法
> *结构体声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [访问级别修饰符](TODO )_可选_ **struct** [*结构体名称*](..\chapter3\05_Declarations.html#struct_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*结构体主体*](..\chapter3\05_Declarations.html#struct_body) > *结构体声明* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [访问级别修饰符](TODO )_可选_ **struct** [*结构体名称*](../chapter3/05_Declarations.html#struct_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承子句*](../chapter3/03_Types.html#type_inheritance_clause) _可选_ [*结构体主体*](../chapter3/05_Declarations.html#struct_body)
> *结构体名称* → [*标识符*](LexicalStructure.html#identifier) > *结构体名称* → [*标识符*](LexicalStructure.html#identifier)
> *结构体主体* → **{** [*声明(Declarations)列表*](..\chapter3\05_Declarations.html#declarations) _可选_ **}** > *结构体主体* → **{** [*声明(Declarations)列表*](../chapter3/05_Declarations.html#declarations) _可选_ **}**
<a name="class_declaration"></a> <a name="class_declaration"></a>
##类声明 ##类声明
@ -620,8 +624,8 @@ num ExampleEnum: Int {
正如在[初始化声明(Initializer Declaration)](TODO)谈及的那样,类可以有指定构造器和方便构造器。类的指定构造器必须初始化类所有的已声明的属性,它必须在超类构造器调用前被执行。 正如在[初始化声明(Initializer Declaration)](TODO)谈及的那样,类可以有指定构造器和方便构造器。类的指定构造器必须初始化类所有的已声明的属性,它必须在超类构造器调用前被执行。
类可以重写属性,方法,下表脚本和它的超类构造器。重写的属性,方法,下标脚本,和指定构造器必须以`override`声明修饰符标记。 类可以重写属性,方法,下表脚本和它的超类构造器。重写的属性,方法,下标脚本,和指定构造器必须以`override`声明修饰符标记。
为了要求子类去实现超类的构造器,使用`required`声明修饰符去标记超类的构造器。在子类实现父类构造器时也必须使用`required`声明修饰符去标记。 为了要求子类去实现超类的构造器,使用`required`声明修饰符去标记超类的构造器。在子类实现父类构造器时也必须使用`required`声明修饰符去标记。
虽然*超类(superclass)*的属性和方法声明可以被当前类继承,但是*超类(superclass)*声明的指定构造器却不能。这意味着如果当前类重写了超类的所有指定构造器它就继承了超类的方便构造器。Swift的类并不是继承自一个全局基础类。 虽然*超类(superclass)*的属性和方法声明可以被当前类继承,但是*超类(superclass)*声明的指定构造器却不能。这意味着如果当前类重写了超类的所有指定构造器它就继承了超类的方便构造器。Swift的类并不是继承自一个全局基础类。
@ -629,7 +633,7 @@ num ExampleEnum: Int {
有两种方法来创建已声明的类的实例: 有两种方法来创建已声明的类的实例:
* 调用类的一个构造器,参见[构造器(Initializers)](TODO)。 * 调用类的一个构造器,参见[构造器(Initializers)](TODO)。
* 如果没有声明构造器,而且类的所有属性都被赋予了初始值,调用类的默认构造器,参见[默认构造器(Default Initializers)](TODO)。 * 如果没有声明构造器,而且类的所有属性都被赋予了初始值,调用类的默认构造器,参见[默认构造器(Default Initializers)](TODO)。
类实例属性可以用点(.)来获得,详情参见[获得属性(Accessing Properties)](TODO)一节。 类实例属性可以用点(.)来获得,详情参见[获得属性(Accessing Properties)](TODO)一节。
@ -637,12 +641,12 @@ num ExampleEnum: Int {
类是引用类型;当被赋予常量或变量,函数调用时,类的实例是被引用,而不是复制。获得更多关于引用类型的信息,[结构体和枚举都是值类型(Structures and Enumerations Are Value Types)](TODO)一节。 类是引用类型;当被赋予常量或变量,函数调用时,类的实例是被引用,而不是复制。获得更多关于引用类型的信息,[结构体和枚举都是值类型(Structures and Enumerations Are Value Types)](TODO)一节。
可以使用扩展声明来扩展类的行为,参见[扩展声明(Extension Declaration)](TODO)。 可以使用扩展声明来扩展类的行为,参见[扩展声明(Extension Declaration)](TODO)。
<a name="grammer_of_a_class_declaration"></a> <a name="grammer_of_a_class_declaration"></a>
> 类声明语法 > 类声明语法
> *类声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [访问级别修饰符](TODO)**class** [*类名*](..\chapter3\05_Declarations.html#class_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*类主体*](..\chapter3\05_Declarations.html#class_body) > *类声明* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [访问级别修饰符](TODO)**class** [*类名*](../chapter3/05_Declarations.html#class_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承子句*](../chapter3/03_Types.html#type_inheritance_clause) _可选_ [*类主体*](../chapter3/05_Declarations.html#class_body)
> *类名* → [*标识符*](LexicalStructure.html#identifier) > *类名* → [*标识符*](LexicalStructure.html#identifier)
> *类主体* → **{** [*声明(Declarations)列表*](..\chapter3\05_Declarations.html#declarations) _可选_ **}** > *类主体* → **{** [*声明(Declarations)列表*](../chapter3/05_Declarations.html#declarations) _可选_ **}**
<a name="protocol_declaration"></a> <a name="protocol_declaration"></a>
##协议声明(translated by 小一) ##协议声明(translated by 小一)
@ -664,14 +668,14 @@ num ExampleEnum: Int {
默认地,符合某一个协议的类型必须实现所有声明在协议中的属性、方法和下标脚本。也就是说,可以用`optional`声明修饰符标注这些协议成员声明以指定它们的一致性类型实现是可选的。`optional`修饰符仅仅可以用于使用`objc`属性标记过的协议。这样的结果就是仅仅类类型可以采用并符合包含可选成员要求的协议。更多关于如何使用`optional`属性的信息及如何访问可选协议成员的指导——比如当不能肯定是否一致性的类型实现了它们——参见[可选协议要求(Optional Protocol Requirements)](../chapter2/21_Protocols.html#optional_protocol_requirements) 默认地,符合某一个协议的类型必须实现所有声明在协议中的属性、方法和下标脚本。也就是说,可以用`optional`声明修饰符标注这些协议成员声明以指定它们的一致性类型实现是可选的。`optional`修饰符仅仅可以用于使用`objc`属性标记过的协议。这样的结果就是仅仅类类型可以采用并符合包含可选成员要求的协议。更多关于如何使用`optional`属性的信息及如何访问可选协议成员的指导——比如当不能肯定是否一致性的类型实现了它们——参见[可选协议要求(Optional Protocol Requirements)](../chapter2/21_Protocols.html#optional_protocol_requirements)
为了限制协议的采用仅仅针对类类型,需要强制使用`class`来标记协议,通过将`class`关键在写在冒号后面的*继承协议列表(inherited protocols)*的第一个位置。例如,下面的协议形式只能被类类型采用: 为了限制协议的采用仅仅针对类类型,需要强制使用`class`来标记协议,通过将`class`关键在写在冒号后面的*继承协议列表(inherited protocols)*的第一个位置。例如,下面的协议形式只能被类类型采用:
```swift ```swift
protocol SomeProtocol:class{ protocol SomeProtocol:class{
/* Protocol member go here */ /* Protocol member go here */
} }
``` ```
任意继承自需要标记有`class`协议的协议都可以智能地仅能被类类型采用。 任意继承自需要标记有`class`协议的协议都可以智能地仅能被类类型采用。
>注意: >注意:
@ -680,18 +684,18 @@ protocol SomeProtocol:class{
协议是命名的类型,因此它们可以以另一个命名类型出现在代码的所有地方,就像[协议类型(Protocol as Types)](../chapter2/21_Protocols.html#protocols_as_types)里讨论的那样。然而不能构造一个协议的实例,因为协议实际上不提供它们指定的要求的实现。 协议是命名的类型,因此它们可以以另一个命名类型出现在代码的所有地方,就像[协议类型(Protocol as Types)](../chapter2/21_Protocols.html#protocols_as_types)里讨论的那样。然而不能构造一个协议的实例,因为协议实际上不提供它们指定的要求的实现。
可以使用协议来声明一个类的代理的方法或者应该实现的结构,就像[委托(代理)模式(Delegation)](../chapter2/21_Protocols.html#delegation)描述的那样。 可以使用协议来声明一个类的代理的方法或者应该实现的结构,就像[委托(代理)模式(Delegation)](../chapter2/21_Protocols.html#delegation)描述的那样。
<a name="grammer_of_a_protocol_declaration"></a> <a name="grammer_of_a_protocol_declaration"></a>
> 协议(Protocol)声明语法 > 协议(Protocol)声明语法
> *协议声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*访问级别修饰符*](TODO) _可选_ **protocol** [*协议名*](..\chapter3\05_Declarations.html#protocol_name) [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*协议主体*](..\chapter3\05_Declarations.html#protocol_body) > *协议声明* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*访问级别修饰符*](TODO) _可选_ **protocol** [*协议名*](../chapter3/05_Declarations.html#protocol_name) [*类型继承子句*](../chapter3/03_Types.html#type_inheritance_clause) _可选_ [*协议主体*](../chapter3/05_Declarations.html#protocol_body)
> *协议名* → [*标识符*](LexicalStructure.html#identifier) > *协议名* → [*标识符*](LexicalStructure.html#identifier)
> *协议主体* → **{** [*协议成员声明(Declarations)列表*](..\chapter3\05_Declarations.html#protocol_member_declarations) _可选_ **}** > *协议主体* → **{** [*协议成员声明(Declarations)列表*](../chapter3/05_Declarations.html#protocol_member_declarations) _可选_ **}**
> *协议成员声明* → [*协议属性声明*](..\chapter3\05_Declarations.html#protocol_property_declaration) > *协议成员声明* → [*协议属性声明*](../chapter3/05_Declarations.html#protocol_property_declaration)
> *协议成员声明* → [*协议方法声明*](..\chapter3\05_Declarations.html#protocol_method_declaration) > *协议成员声明* → [*协议方法声明*](../chapter3/05_Declarations.html#protocol_method_declaration)
> *协议成员声明* → [*协议构造器声明*](..\chapter3\05_Declarations.html#protocol_initializer_declaration) > *协议成员声明* → [*协议构造器声明*](../chapter3/05_Declarations.html#protocol_initializer_declaration)
> *协议成员声明* → [*协议附属脚本声明*](..\chapter3\05_Declarations.html#protocol_subscript_declaration) > *协议成员声明* → [*协议附属脚本声明*](../chapter3/05_Declarations.html#protocol_subscript_declaration)
> *协议成员声明* → [*协议关联类型声明*](..\chapter3\05_Declarations.html#protocol_associated_type_declaration) > *协议成员声明* → [*协议关联类型声明*](../chapter3/05_Declarations.html#protocol_associated_type_declaration)
> *协议成员声明(Declarations)列表* → [*协议成员声明*](..\chapter3\05_Declarations.html#protocol_member_declaration) [*协议成员声明(Declarations)列表*](..\chapter3\05_Declarations.html#protocol_member_declarations) _可选_ > *协议成员声明(Declarations)列表* → [*协议成员声明*](../chapter3/05_Declarations.html#protocol_member_declaration) [*协议成员声明(Declarations)列表*](../chapter3/05_Declarations.html#protocol_member_declarations) _可选_
<a name="protocol_property_declaration"></a> <a name="protocol_property_declaration"></a>
###协议属性声明 ###协议属性声明
@ -705,11 +709,11 @@ protocol SomeProtocol:class{
`getter``setter`要求可以通过一致性类型以各种方式满足。如果属性声明包含`get``set`关键词,一致性类型就可以用可读写(实现了`getter``setter`)的存储型变量属性或计算型属性,但是属性不能以常量属性或只读计算型属性实现。如果属性声明仅仅包含`get`关键词的话,它可以作为任意类型的属性被实现。比如说实现了协议的属性要求的一致性类型,参见[属性要求(Property Requirements)](../chapter2/21_Protocols.html#property_requirements) `getter``setter`要求可以通过一致性类型以各种方式满足。如果属性声明包含`get``set`关键词,一致性类型就可以用可读写(实现了`getter``setter`)的存储型变量属性或计算型属性,但是属性不能以常量属性或只读计算型属性实现。如果属性声明仅仅包含`get`关键词的话,它可以作为任意类型的属性被实现。比如说实现了协议的属性要求的一致性类型,参见[属性要求(Property Requirements)](../chapter2/21_Protocols.html#property_requirements)
更多参见[变量声明(Variabel Declaration)](../chapter3/05_Declarations.html#variable_declaration) 更多参见[变量声明(Variabel Declaration)](../chapter3/05_Declarations.html#variable_declaration)
<a name="grammer_of_an_import_declaration"></a> <a name="grammer_of_an_import_declaration"></a>
> 协议属性声明语法 > 协议属性声明语法
> *协议属性声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型标注*](..\chapter3\03_Types.html#type_annotation) [*getter-setter关键字(Keyword)块*](..\chapter3\05_Declarations.html#getter_setter_keyword_block) > *协议属性声明* → [*变量声明头(Head)*](../chapter3/05_Declarations.html#variable_declaration_head) [*变量名*](../chapter3/05_Declarations.html#variable_name) [*类型标注*](../chapter3/03_Types.html#type_annotation) [*getter-setter关键字(Keyword)块*](../chapter3/05_Declarations.html#getter_setter_keyword_block)
<a name="protocol_method_declaration"></a> <a name="protocol_method_declaration"></a>
###协议方法声明 ###协议方法声明
@ -718,27 +722,27 @@ protocol SomeProtocol:class{
使用`static`声明修饰符可以在协议声明中声明一个类或必需的静态方法。执行这些方法的类用修饰符`class`声明。相反的,执行这些方法的结构体必须以`static`声明修饰符声明。如果想使用扩展方法,在扩展类时使用`class`修饰符,在扩展结构体时使用`static`修饰符。 使用`static`声明修饰符可以在协议声明中声明一个类或必需的静态方法。执行这些方法的类用修饰符`class`声明。相反的,执行这些方法的结构体必须以`static`声明修饰符声明。如果想使用扩展方法,在扩展类时使用`class`修饰符,在扩展结构体时使用`static`修饰符。
更多请参阅[函数声明(Function Declaration)](TODO)。 更多请参阅[函数声明(Function Declaration)](TODO)。
<a name="grammer_of_a_protocol_declaration"></a> <a name="grammer_of_a_protocol_declaration"></a>
> 协议方法声明语法 > 协议方法声明语法
> *协议方法声明* → [*函数头*](..\chapter3\05_Declarations.html#function_head) [*函数名*](..\chapter3\05_Declarations.html#function_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*函数签名(Signature)*](..\chapter3\05_Declarations.html#function_signature) > *协议方法声明* → [*函数头*](../chapter3/05_Declarations.html#function_head) [*函数名*](../chapter3/05_Declarations.html#function_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*函数签名(Signature)*](../chapter3/05_Declarations.html#function_signature)
<a name="protocol_initializer_declaration"></a> <a name="protocol_initializer_declaration"></a>
###协议构造器声明 ###协议构造器声明
协议声明了一致性类型必须在协议声明的主体里通过引入一个协议构造器声明来实现一个构造器。协议构造器声明 协议声明了一致性类型必须在协议声明的主体里通过引入一个协议构造器声明来实现一个构造器。协议构造器声明
除了不包含构造器体外,和构造器声明有着相同的形式。 除了不包含构造器体外,和构造器声明有着相同的形式。
一个一致性类型可以通过实现一个非可失败构造器或者`init!`可失败构造器去满足一个非可失败协议构造器的需求。一个一致性类型通过实现任意类型的构造器可以满足一个可失败协议构造器的需求。 一个一致性类型可以通过实现一个非可失败构造器或者`init!`可失败构造器去满足一个非可失败协议构造器的需求。一个一致性类型通过实现任意类型的构造器可以满足一个可失败协议构造器的需求。
当一个类去实现一个构造器去满足一个协议的构造器的需求,如果这个类还没有用`final`声明修饰符标记,这个构造器必需使用`required`声明修饰符去标记。 当一个类去实现一个构造器去满足一个协议的构造器的需求,如果这个类还没有用`final`声明修饰符标记,这个构造器必需使用`required`声明修饰符去标记。
更多请参阅[构造器声明(Initializer Declaration)](TODO)。 更多请参阅[构造器声明(Initializer Declaration)](TODO)。
<a name="grammer_of_a_protocol_initializer_declaration"></a> <a name="grammer_of_a_protocol_initializer_declaration"></a>
> 协议构造器声明语法 > 协议构造器声明语法
> *协议构造器声明* → [*构造器头(Head)*](..\chapter3\05_Declarations.html#initializer_head) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) > *协议构造器声明* → [*构造器头(Head)*](../chapter3/05_Declarations.html#initializer_head) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*参数子句*](../chapter3/05_Declarations.html#parameter_clause)
<a name="protocol_subscript_declaration"></a> <a name="protocol_subscript_declaration"></a>
###协议下标脚本声明 ###协议下标脚本声明
@ -749,19 +753,19 @@ protocol SomeProtocol:class{
下标脚本声明只为和协议一致的类型声明了必需的最小数量的的getter和setter。如果下标脚本申明包含get和set关键字一致的类型也必须有一个getter和setter语句。如果下标脚本声明值包含get关键字一致的类型必须*至少(at least)*包含一个getter语句可以选择是否包含setter语句。 下标脚本声明只为和协议一致的类型声明了必需的最小数量的的getter和setter。如果下标脚本申明包含get和set关键字一致的类型也必须有一个getter和setter语句。如果下标脚本声明值包含get关键字一致的类型必须*至少(at least)*包含一个getter语句可以选择是否包含setter语句。
更多参阅[下标脚本声明(Subscript Declaration)](TODO)。 更多参阅[下标脚本声明(Subscript Declaration)](TODO)。
<a name="grammer_of_a_protocol_subscript_declaration"></a> <a name="grammer_of_a_protocol_subscript_declaration"></a>
> 协议附属脚本声明语法 > 协议附属脚本声明语法
> *协议附属脚本声明* → [*附属脚本头(Head)*](..\chapter3\05_Declarations.html#subscript_head) [*附属脚本结果(Result)*](..\chapter3\05_Declarations.html#subscript_result) [*getter-setter关键字(Keyword)块*](..\chapter3\05_Declarations.html#getter_setter_keyword_block) > *协议附属脚本声明* → [*附属脚本头(Head)*](../chapter3/05_Declarations.html#subscript_head) [*附属脚本结果(Result)*](../chapter3/05_Declarations.html#subscript_result) [*getter-setter关键字(Keyword)块*](../chapter3/05_Declarations.html#getter_setter_keyword_block)
<a name="protocol_associated_type_declaration"></a> <a name="protocol_associated_type_declaration"></a>
###协议相关类型声明 ###协议相关类型声明
协议声明相关类型使用关键字`typealias`。相关类型为作为协议声明的一部分的类型提供了一个别名。相关类型和参数语句中的类型参数很相似,但是它们在声明的协议中包含`self`关键字。在这些语句中,`self`指代和协议一致的可能的类型。获得更多信息和例子,查看[关联类型(Associated Types)](TODO)一节或[类型别名声明(Type Alias Declaration)](TODO)一节。 协议声明相关类型使用关键字`typealias`。相关类型为作为协议声明的一部分的类型提供了一个别名。相关类型和参数语句中的类型参数很相似,但是它们在声明的协议中包含`self`关键字。在这些语句中,`self`指代和协议一致的可能的类型。获得更多信息和例子,查看[关联类型(Associated Types)](TODO)一节或[类型别名声明(Type Alias Declaration)](TODO)一节。
<a name="grammer_of_a_protocol_associated_type_declaration"></a> <a name="grammer_of_a_protocol_associated_type_declaration"></a>
> 协议关联类型声明语法 > 协议关联类型声明语法
> *协议关联类型声明* → [*类型别名头(Head)*](..\chapter3\05_Declarations.html#typealias_head) [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*类型别名赋值*](..\chapter3\05_Declarations.html#typealias_assignment) _可选_ > *协议关联类型声明* → [*类型别名头(Head)*](../chapter3/05_Declarations.html#typealias_head) [*类型继承子句*](../chapter3/03_Types.html#type_inheritance_clause) _可选_ [*类型别名赋值*](../chapter3/05_Declarations.html#typealias_assignment) _可选_
<a name="initializer_declaration"></a> <a name="initializer_declaration"></a>
##构造器声明 ##构造器声明
@ -791,64 +795,64 @@ protocol SomeProtocol:class{
便利构造器可以将初始化过程委托给另一个便利构造器或类的一个指定构造器。这意味着,类的初始化过程必须 便利构造器可以将初始化过程委托给另一个便利构造器或类的一个指定构造器。这意味着,类的初始化过程必须
以一个将所有类属性完全初始化的指定构造器的调用作为结束。便利构造器不能调用超类的构造器。 以一个将所有类属性完全初始化的指定构造器的调用作为结束。便利构造器不能调用超类的构造器。
可以使用required声明修饰符将便利构造器和指定构造器标记为每个子类的构造器都必须实现的。一个子类的关于这个构造器的实现也必须使用`required`声明修饰符标记。 可以使用required声明修饰符将便利构造器和指定构造器标记为每个子类的构造器都必须实现的。一个子类的关于这个构造器的实现也必须使用`required`声明修饰符标记。
默认情况下,声明在超类的构造器没有被子类继承。也就是说,如果一个子类使用默认的值去构造它所有的存储属性,而且没有定义任何自己的构造器,它将继承超类的构造器。如果子类重写所有超类的指定构造器,子类继承超类的便利构造器。 默认情况下,声明在超类的构造器没有被子类继承。也就是说,如果一个子类使用默认的值去构造它所有的存储属性,而且没有定义任何自己的构造器,它将继承超类的构造器。如果子类重写所有超类的指定构造器,子类继承超类的便利构造器。
和方法,属性和下表脚本一样,需要使用`override`声明修饰符标记重写了的制定构造器。 和方法,属性和下表脚本一样,需要使用`override`声明修饰符标记重写了的制定构造器。
>注意 >注意
>如果使用`required`声明修饰符去标记一个构造器,当在子类中重写必要构造器时,也不要用`override`修饰符去标记构造器。 >如果使用`required`声明修饰符去标记一个构造器,当在子类中重写必要构造器时,也不要用`override`修饰符去标记构造器。
查看更多关于不同声明方法的构造器的例子,参阅[构造过程(Initialization)](TODO)一节。 查看更多关于不同声明方法的构造器的例子,参阅[构造过程(Initialization)](TODO)一节。
<a name="failable_initializers"></a> <a name="failable_initializers"></a>
###可失败构造器(Failable Initializers) ###可失败构造器(Failable Initializers)
*可失败构造器*是一种可以生成可选实例或者是一类构造器声明的隐式解析可选实例(an implicitly unwrapped optional instance)类型。所以,构造区通过返回`nil`来指明构造过程失败。 *可失败构造器*是一种可以生成可选实例或者是一类构造器声明的隐式解析可选实例(an implicitly unwrapped optional instance)类型。所以,构造区通过返回`nil`来指明构造过程失败。
声明可以生成可选实例的可失败构造器,在构造器声明的`init`关键字后加追加一个问号(`init?`)。声明可生成隐式解析可选实例的可失败构造器,在构造器声明后追加一个叹号(`init!`)。使用`init?`可失败构造器生成结构体的一个可选实例的例子如下。 声明可以生成可选实例的可失败构造器,在构造器声明的`init`关键字后加追加一个问号(`init?`)。声明可生成隐式解析可选实例的可失败构造器,在构造器声明后追加一个叹号(`init!`)。使用`init?`可失败构造器生成结构体的一个可选实例的例子如下。
```swift ```swift
struct SomeStruct { struct SomeStruct {
let string: String let string: String
//生成一个'SomeStruct'的可选实例 //生成一个'SomeStruct'的可选实例
init?(input: String) { init?(input: String) {
if input.isEmpty { if input.isEmpty {
// 弃用'self' 返回 'nil' // 弃用'self' 返回 'nil'
} }
string = input string = input
} }
} }
``` ```
除非必需处理结果的可选性,可以使用调用非可失败构造器的方式调用`init?`可失败构造器。 除非必需处理结果的可选性,可以使用调用非可失败构造器的方式调用`init?`可失败构造器。
```swift ```swift
if let actualInstance = SomeStruct(input: "Hello") { if let actualInstance = SomeStruct(input: "Hello") {
//'SomeStruct'实例相关 //'SomeStruct'实例相关
} else { } else {
//'SomeStruct'实例构造过程失败,构造器返回'nil' //'SomeStruct'实例构造过程失败,构造器返回'nil'
} }
``` ```
在实现构造体的任何时间,结构体或者枚举的可失败构造器可以返回`nil`。然而,类的可失败构造器,仅在类的所有存储属性被构造之后且`self.init``super.init`被调用之后才返回`nil`(就是说,构造器的委托被执行)。
可失败构造器可以委托任何种类的构造器。非可失败可以委托其它非可失败构造器或者`init!`可失败构造器。
构造过程的失败由构造器的委托产生。特别的,如果可失败构造器代理一个构造器失败且返回`nil`,那么之后被委托的构造器也会失败且隐式的返回`nil`。如果非可失败构造器代理`init!`可失败构造器失败了且返回`nil`,那么后出现一个运行时错误(如同使用`!`操作符去解析一个有着`nil`值的可选项)。
可失败指定构造器可以在子类中任何一种指定构造器重写。非可失败指定构造器在子类中仅能通过非可失败构造器被重写。
得到更多的信息并且了解更多关于可失败构造器的例子,请参阅[可失败构造器(Failable Initializer)](TODO)
在实现构造体的任何时间,结构体或者枚举的可失败构造器可以返回`nil`。然而,类的可失败构造器,仅在类的所有存储属性被构造之后且`self.init``super.init`被调用之后才返回`nil`(就是说,构造器的委托被执行)。
可失败构造器可以委托任何种类的构造器。非可失败可以委托其它非可失败构造器或者`init!`可失败构造器。
构造过程的失败由构造器的委托产生。特别的,如果可失败构造器代理一个构造器失败且返回`nil`,那么之后被委托的构造器也会失败且隐式的返回`nil`。如果非可失败构造器代理`init!`可失败构造器失败了且返回`nil`,那么后出现一个运行时错误(如同使用`!`操作符去解析一个有着`nil`值的可选项)。
可失败指定构造器可以在子类中任何一种指定构造器重写。非可失败指定构造器在子类中仅能通过非可失败构造器被重写。
得到更多的信息并且了解更多关于可失败构造器的例子,请参阅[可失败构造器(Failable Initializer)](TODO)
<a name="grammer_of_an_initializer_declaration"></a> <a name="grammer_of_an_initializer_declaration"></a>
> 构造器声明语法 > 构造器声明语法
> *构造器声明* → [*构造器头(Head)*](..\chapter3\05_Declarations.html#initializer_head) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*构造器主体*](..\chapter3\05_Declarations.html#initializer_body) > *构造器声明* → [*构造器头(Head)*](../chapter3/05_Declarations.html#initializer_head) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*参数子句*](../chapter3/05_Declarations.html#parameter_clause) [*构造器主体*](../chapter3/05_Declarations.html#initializer_body)
> *构造器头(Head)* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修饰符列表(modifiers)*](TODO) _可选_ **init** > *构造器头(Head)* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*声明修饰符列表(modifiers)*](TODO) _可选_ **init**
> *构造器头(Head)* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修饰符列表(modifiers)*](TODO) _可选_ **init ?** > *构造器头(Head)* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*声明修饰符列表(modifiers)*](TODO) _可选_ **init ?**
> *构造器头(Head)* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修饰符列表(modifiers)*](TODO) _可选_ **init !** > *构造器头(Head)* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*声明修饰符列表(modifiers)*](TODO) _可选_ **init !**
> *构造器主体* → [*代码块*](..\chapter3\05_Declarations.html#code_block) > *构造器主体* → [*代码块*](../chapter3/05_Declarations.html#code_block)
<a name="deinitializer_declaration"></a> <a name="deinitializer_declaration"></a>
##析构声明 ##析构声明
@ -867,10 +871,10 @@ if let actualInstance = SomeStruct(input: "Hello") {
析构器不会被直接调用。 析构器不会被直接调用。
查看例子和如何在类的声明中使用析构器,参见[析构过程Deinitialization](TODO)一节。 查看例子和如何在类的声明中使用析构器,参见[析构过程Deinitialization](TODO)一节。
<a name="grammer_of_a_deinitializer_declaration"></a> <a name="grammer_of_a_deinitializer_declaration"></a>
> 析构器声明语法 > 析构器声明语法
> *析构器声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **deinit** [*代码块*](..\chapter3\05_Declarations.html#code_block) > *析构器声明* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ **deinit** [*代码块*](../chapter3/05_Declarations.html#code_block)
<a name="extension_declaration"></a> <a name="extension_declaration"></a>
##扩展声明 ##扩展声明
@ -889,15 +893,15 @@ if let actualInstance = SomeStruct(input: "Hello") {
扩展声明可以包含构造器声明,这意味着,如果扩展的类型在其他模块中定义,构造器声明必须委托另一个在 扩展声明可以包含构造器声明,这意味着,如果扩展的类型在其他模块中定义,构造器声明必须委托另一个在
那个模块里声明的构造器来恰当的初始化。 那个模块里声明的构造器来恰当的初始化。
<a name="grammer_of_an_extension_declaration"></a> <a name="grammer_of_an_extension_declaration"></a>
> 扩展(Extension)声明语法 > 扩展(Extension)声明语法
> *扩展声明* → [访问级别修饰符](TODO) _可选_ **extension** [*类型标识*](..\chapter3\03_Types.html#type_identifier) [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*extension-body*](..\chapter3\05_Declarations.html#extension_body) > *扩展声明* → [访问级别修饰符](TODO) _可选_ **extension** [*类型标识*](../chapter3/03_Types.html#type_identifier) [*类型继承子句*](../chapter3/03_Types.html#type_inheritance_clause) _可选_ [*extension-body*](../chapter3/05_Declarations.html#extension_body)
> *extension-body* → **{** [*声明(Declarations)列表*](..\chapter3\05_Declarations.html#declarations) _可选_ **}** > *extension-body* → **{** [*声明(Declarations)列表*](../chapter3/05_Declarations.html#declarations) _可选_ **}**
<a name="subscript_declaration"></a> <a name="subscript_declaration"></a>
##下标脚本声明 ##下标脚本声明
*下标脚本(subscript)*声明用于向特定类型添加附属脚本支持,通常为访问集合,列表和序列的元素时提供语法便利。附属脚本声明使用关键字`subscript`,声明形式如下: *下标脚本(subscript)*声明用于向特定类型添加附属脚本支持,通常为访问集合,列表和序列的元素时提供语法便利。附属脚本声明使用关键字`subscript`,声明形式如下:
> subscript (`parameter`) -> (return type){ > subscript (`parameter`) -> (return type){
@ -922,22 +926,22 @@ if let actualInstance = SomeStruct(input: "Hello") {
同样可以在协议声明的上下文中声明下标脚本,[协议下标脚本声明(Protocol Subscript Declaration)](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-XID_619)中有所描述。 同样可以在协议声明的上下文中声明下标脚本,[协议下标脚本声明(Protocol Subscript Declaration)](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-XID_619)中有所描述。
更多关于下标脚本和下标脚本声明的例子,请参考[下标脚本(Subscripts)](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Subscripts.html#//apple_ref/doc/uid/TP40014097-CH16-XID_393)。 更多关于下标脚本和下标脚本声明的例子,请参考[下标脚本(Subscripts)](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Subscripts.html#//apple_ref/doc/uid/TP40014097-CH16-XID_393)。
<a name="grammer_of_a_subscript_declaration"></a> <a name="grammer_of_a_subscript_declaration"></a>
> 附属脚本声明语法 > 附属脚本声明语法
> *附属脚本声明* → [*附属脚本头(Head)*](..\chapter3\05_Declarations.html#subscript_head) [*附属脚本结果(Result)*](..\chapter3\05_Declarations.html#subscript_result) [*代码块*](..\chapter3\05_Declarations.html#code_block) > *附属脚本声明* → [*附属脚本头(Head)*](../chapter3/05_Declarations.html#subscript_head) [*附属脚本结果(Result)*](../chapter3/05_Declarations.html#subscript_result) [*代码块*](../chapter3/05_Declarations.html#code_block)
> *附属脚本声明* → [*附属脚本头(Head)*](..\chapter3\05_Declarations.html#subscript_head) [*附属脚本结果(Result)*](..\chapter3\05_Declarations.html#subscript_result) [*getter-setter块*](..\chapter3\05_Declarations.html#getter_setter_block) > *附属脚本声明* → [*附属脚本头(Head)*](../chapter3/05_Declarations.html#subscript_head) [*附属脚本结果(Result)*](../chapter3/05_Declarations.html#subscript_result) [*getter-setter块*](../chapter3/05_Declarations.html#getter_setter_block)
> *附属脚本声明* → [*附属脚本头(Head)*](..\chapter3\05_Declarations.html#subscript_head) [*附属脚本结果(Result)*](..\chapter3\05_Declarations.html#subscript_result) [*getter-setter关键字(Keyword)块*](..\chapter3\05_Declarations.html#getter_setter_keyword_block) > *附属脚本声明* → [*附属脚本头(Head)*](../chapter3/05_Declarations.html#subscript_head) [*附属脚本结果(Result)*](../chapter3/05_Declarations.html#subscript_result) [*getter-setter关键字(Keyword)块*](../chapter3/05_Declarations.html#getter_setter_keyword_block)
> *附属脚本头(Head)* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修饰符列表(declaration-modifiers)*](TODO) _可选_ **subscript** [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) > *附属脚本头(Head)* → [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*声明修饰符列表(declaration-modifiers)*](TODO) _可选_ **subscript** [*参数子句*](../chapter3/05_Declarations.html#parameter_clause)
> *附属脚本结果(Result)* → **->** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type) > *附属脚本结果(Result)* → **->** [*特性(Attributes)列表*](../chapter3/06_Attributes.html#attributes) _可选_ [*类型*](../chapter3/03_Types.html#type)
<a name="operator_declaration"></a> <a name="operator_declaration"></a>
##运算符声明(translated by 林) ##运算符声明(translated by 林)
*运算符声明(operator declaration)*会向程序中引入中缀、前缀或后缀运算符,它使用关键字`operator`声明。 *运算符声明(operator declaration)*会向程序中引入中缀、前缀或后缀运算符,它使用关键字`operator`声明。
可以声明三种不同的缀性:中缀、前缀和后缀。操作符的*缀性(fixity)*描述了操作符与它的操作数的相对位置。 可以声明三种不同的缀性:中缀、前缀和后缀。操作符的*缀性(fixity)*描述了操作符与它的操作数的相对位置。
运算符声明有三种基本形式,每种缀性各一种。运算符的缀性通过在`operator`关键字之前添加声明修饰符`infix``prefix``postfix`来指定。每种形式中,运算符的名字只能包含[运算符(Operators)](TODO)中定义的运算符字符。 运算符声明有三种基本形式,每种缀性各一种。运算符的缀性通过在`operator`关键字之前添加声明修饰符`infix``prefix``postfix`来指定。每种形式中,运算符的名字只能包含[运算符(Operators)](TODO)中定义的运算符字符。
下面的这种形式声明了一个新的中缀运算符: 下面的这种形式声明了一个新的中缀运算符:
@ -973,17 +977,17 @@ if let actualInstance = SomeStruct(input: "Hello") {
和前缀运算符一样,后缀运算符的声明中不指定优先级。后缀运算符是非结合的。 和前缀运算符一样,后缀运算符的声明中不指定优先级。后缀运算符是非结合的。
声明了一个新的运算符以后,需要声明一个跟这个运算符同名的函数来实现这个运算符。如果在实现一个前缀或者后缀操作符,也必须使用相符的`prefix`或者`postfix`声明修饰符标记函数声明。如果实现中缀操作符,不需要使用`infix`声明修饰符标记函数声明。如何实现一个新的运算符,请参考[Custom Operators](TODO)。 声明了一个新的运算符以后,需要声明一个跟这个运算符同名的函数来实现这个运算符。如果在实现一个前缀或者后缀操作符,也必须使用相符的`prefix`或者`postfix`声明修饰符标记函数声明。如果实现中缀操作符,不需要使用`infix`声明修饰符标记函数声明。如何实现一个新的运算符,请参考[Custom Operators](TODO)。
<a name="grammer_of_an_operator_declaration"></a> <a name="grammer_of_an_operator_declaration"></a>
> 运算符声明语法 > 运算符声明语法
> *运算符声明* → [*前置运算符声明*](..\chapter3\05_Declarations.html#prefix_operator_declaration) | [*后置运算符声明*](..\chapter3\05_Declarations.html#postfix_operator_declaration) | [*中置运算符声明*](..\chapter3\05_Declarations.html#infix_operator_declaration) > *运算符声明* → [*前置运算符声明*](../chapter3/05_Declarations.html#prefix_operator_declaration) | [*后置运算符声明*](../chapter3/05_Declarations.html#postfix_operator_declaration) | [*中置运算符声明*](../chapter3/05_Declarations.html#infix_operator_declaration)
> *前置运算符声明* → **prefix** **运算符** [*运算符*](LexicalStructure.html#operator) **{** **}** > *前置运算符声明* → **prefix** **运算符** [*运算符*](LexicalStructure.html#operator) **{** **}**
> *后置运算符声明* → **postfix** **运算符** [*运算符*](LexicalStructure.html#operator) **{** **}** > *后置运算符声明* → **postfix** **运算符** [*运算符*](LexicalStructure.html#operator) **{** **}**
> *中置运算符声明* → **infix** **运算符** [*运算符*](LexicalStructure.html#operator) **{** [*中置运算符属性*](..\chapter3\05_Declarations.html#infix_operator_attributes) _可选_ **}** > *中置运算符声明* → **infix** **运算符** [*运算符*](LexicalStructure.html#operator) **{** [*中置运算符属性*](../chapter3/05_Declarations.html#infix_operator_attributes) _可选_ **}**
> *中置运算符属性* → [*优先级子句*](..\chapter3\05_Declarations.html#precedence_clause) _可选_ [*结和性子句*](..\chapter3\05_Declarations.html#associativity_clause) _可选_ > *中置运算符属性* → [*优先级子句*](../chapter3/05_Declarations.html#precedence_clause) _可选_ [*结和性子句*](../chapter3/05_Declarations.html#associativity_clause) _可选_
> *优先级子句* → **precedence** [*优先级水平*](..\chapter3\05_Declarations.html#precedence_level) > *优先级子句* → **precedence** [*优先级水平*](../chapter3/05_Declarations.html#precedence_level)
> *优先级水平* → 十进制整数 0 到 255 > *优先级水平* → 十进制整数 0 到 255
> *结和性子句* → **associativity** [*结和性*](..\chapter3\05_Declarations.html#associativity) > *结和性子句* → **associativity** [*结和性*](../chapter3/05_Declarations.html#associativity)
> *结和性* → **left** | **right** | **none** > *结和性* → **left** | **right** | **none**
@ -1017,7 +1021,7 @@ if let actualInstance = SomeStruct(input: "Hello") {
`weak` `weak`
`weak`修饰符用于修饰一个变量或一个存储型变量属性,表示该变量或属性通过一个弱引用指向存储其值的对象。该变量或属性的类型必须是一个可选类类型。通过`weak`修饰符可避免强引用循环。关于`weak`修饰符的例子和更多信息,可以参见[弱引用(Weak References)](TODO)一章 `weak`修饰符用于修饰一个变量或一个存储型变量属性,表示该变量或属性通过一个弱引用指向存储其值的对象。该变量或属性的类型必须是一个可选类类型。通过`weak`修饰符可避免强引用循环。关于`weak`修饰符的例子和更多信息,可以参见[弱引用(Weak References)](TODO)一章
<a name="access_control_levels"></a> <a name="access_control_levels"></a>
### 访问控制级别 ### 访问控制级别
@ -1038,7 +1042,7 @@ Swift提供了三个级别的权限控制`public`, `internal`, 和 `private`
以上的任意一个权限级别修饰符都可以有选择的带上一个参数,该参数由关键字`set`和一对括号组成(比如,`private(set)`。当想要指明一个变量或下标脚注的setter的访问级别要低于或等于该变量或下标脚注的实际访问级别时使用这种格式的权限级别修饰符就像[Getters and Setters](TODO)一章中讨论的一样。 以上的任意一个权限级别修饰符都可以有选择的带上一个参数,该参数由关键字`set`和一对括号组成(比如,`private(set)`。当想要指明一个变量或下标脚注的setter的访问级别要低于或等于该变量或下标脚注的实际访问级别时使用这种格式的权限级别修饰符就像[Getters and Setters](TODO)一章中讨论的一样。
<a name="grammer_of_a_declaration_modifier"></a> <a name="grammer_of_a_declaration_modifier"></a>
>声明修饰符的语法 >声明修饰符的语法
@ -1050,7 +1054,7 @@ Swift提供了三个级别的权限控制`public`, `internal`, 和 `private`
> >
>访问级别修饰符 → **private­** | **private­(­set­)­** >访问级别修饰符 → **private­** | **private­(­set­)­**
> >
>访问级别修饰符 → **public­** | **public­(­set­)­** >访问级别修饰符 → **public­** | **public­(­set­)­**
> >
>访问级别修饰符 → [访问级别修饰符(access-level-modeifier)](TODO) [访问级别修饰符列表(access-level-modeifiers)](TODO) _可选_ >访问级别修饰符 → [访问级别修饰符(access-level-modeifier)](TODO) [访问级别修饰符列表(access-level-modeifiers)](TODO) _可选_
­ ­

View File

@ -1,5 +1,9 @@
> 1.0
> 翻译:[Hawstein](https://github.com/Hawstein) > 翻译:[Hawstein](https://github.com/Hawstein)
> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai), [KYawn](https://github.com/KYawn) > 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[KYawn](https://github.com/KYawn)
# 特性 # 特性
----------------- -----------------
@ -25,7 +29,7 @@
`autoclosure` `autoclosure`
这个特性通过把表达式自动封装成无参数的闭包来延迟表达式的计算。它可以声明返回表达式自身类型的没有参数的方法类型,也可以用于函数参数的声明。含有`autoclosure`特性的声明同时也具有`noescape`的特性,除非传递可选参数`escaping`.关于怎样使用`autoclosure`特性的例子,参见[函数类型](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html#//apple_ref/doc/uid/TP40014097-CH31-ID449). 这个特性通过把表达式自动封装成无参数的闭包来延迟表达式的计算。它可以声明返回表达式自身类型的没有参数的方法类型,也可以用于函数参数的声明。含有`autoclosure`特性的声明同时也具有`noescape`的特性,除非传递可选参数`escaping`.关于怎样使用`autoclosure`特性的例子,参见[函数类型](./03_Types.html#function_type).
`available` `available`

View File

@ -1,6 +1,10 @@
> 翻译:[honghaoz](https://github.com/honghaoz), [ray16897188](https://github.com/ray16897188) > 1.0
> 翻译:[honghaoz](https://github.com/honghaoz)
> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai) > 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[ray16897188](https://github.com/ray16897188)
# 模式Patterns # 模式Patterns
----------------- -----------------
@ -24,14 +28,14 @@ swift语言中模式有2个基本的分类一类能成功和任何值的类
第二类模式用于全模式匹配这种情况下你用来相比较的值在运行时可能还不存在。此类模式包括枚举用例模式enumeration case patterns可选模式optional patterns表达式模式expression patterns和类型转换模式type-casting patterns。你在`switch`语句的case标签中`do`语句的`catch`从句中,或者在`if, while, guard``for-in`语句的case条件句中使用这类模式。 第二类模式用于全模式匹配这种情况下你用来相比较的值在运行时可能还不存在。此类模式包括枚举用例模式enumeration case patterns可选模式optional patterns表达式模式expression patterns和类型转换模式type-casting patterns。你在`switch`语句的case标签中`do`语句的`catch`从句中,或者在`if, while, guard``for-in`语句的case条件句中使用这类模式。
> 模式(Patterns) 语法 > 模式(Patterns) 语法
> *模式* → [*通配符模式*](..\chapter3\07_Patterns.html#wildcard_pattern) [*类型标注*](..\chapter3\03_Types.html#type_annotation) _可选_ > *模式* → [*通配符模式*](../chapter3/07_Patterns.html#wildcard_pattern) [*类型标注*](../chapter3/03_Types.html#type_annotation) _可选_
> *模式* → [*标识符模式*](..\chapter3\07_Patterns.html#identifier_pattern) [*类型标注*](..\chapter3\03_Types.html#type_annotati(Value Binding)on) _可选_ > *模式* → [*标识符模式*](../chapter3/07_Patterns.html#identifier_pattern) [*类型标注*](../chapter3/03_Types.html#type_annotati(Value Binding)on) _可选_
> *模式* → [*值绑定模式*](..\chapter3\07_Patterns.html#value_binding_pattern) > *模式* → [*值绑定模式*](../chapter3/07_Patterns.html#value_binding_pattern)
> *模式* → [*元组模式*](..\chapter3\07_Patterns.html#tuple_pattern) [*类型标注*](..\chapter3\03_Types.html#type_annotation) _可选_ > *模式* → [*元组模式*](../chapter3/07_Patterns.html#tuple_pattern) [*类型标注*](../chapter3/03_Types.html#type_annotation) _可选_
> *模式* → [*枚举用例模式*](..\chapter3\07_Patterns.html#enum_case_pattern) > *模式* → [*枚举用例模式*](../chapter3/07_Patterns.html#enum_case_pattern)
> *模式* → [*可选模式*](..\chapter3\07_Patterns.html#optional_pattern) > *模式* → [*可选模式*](../chapter3/07_Patterns.html#optional_pattern)
> *模式* → [*类型转换模式*](..\chapter3\07_Patterns.html#type_casting_pattern) > *模式* → [*类型转换模式*](../chapter3/07_Patterns.html#type_casting_pattern)
> *模式* → [*表达式模式*](..\chapter3\07_Patterns.html#expression_pattern) > *模式* → [*表达式模式*](../chapter3/07_Patterns.html#expression_pattern)
<a name="wildcard_pattern"></a> <a name="wildcard_pattern"></a>
## 通配符模式Wildcard Pattern ## 通配符模式Wildcard Pattern
@ -83,7 +87,7 @@ case let (x, y):
在上面这个例子中,`let`将元组模式`(x, y)`分配到各个标识符模式。正是由于这么做,`switch`语句中`case let (x, y):``case (let x, let y):`匹配到的值是一样的。 在上面这个例子中,`let`将元组模式`(x, y)`分配到各个标识符模式。正是由于这么做,`switch`语句中`case let (x, y):``case (let x, let y):`匹配到的值是一样的。
> 值绑定(Value Binding)模式语法 > 值绑定(Value Binding)模式语法
> *值绑定模式* → **var** [*模式*](..\chapter3\07_Patterns.html#pattern) | **let** [*模式*](..\chapter3\07_Patterns.html#pattern) > *值绑定模式* → **var** [*模式*](../chapter3/07_Patterns.html#pattern) | **let** [*模式*](../chapter3/07_Patterns.html#pattern)
<a name="tuple_pattern"></a> <a name="tuple_pattern"></a>
## 元组模式Tuple Pattern ## 元组模式Tuple Pattern
@ -111,9 +115,9 @@ let (a): Int = 2 // a: Int = 2
``` ```
> 元组模式语法 > 元组模式语法
> *元组模式* → **(** [*元组模式元素列表*](..\chapter3\07_Patterns.html#tuple_pattern_element_list) _可选_ **)** > *元组模式* → **(** [*元组模式元素列表*](../chapter3/07_Patterns.html#tuple_pattern_element_list) _可选_ **)**
> *元组模式元素列表* → [*元组模式元素*](..\chapter3\07_Patterns.html#tuple_pattern_element) | [*元组模式元素*](..\chapter3\07_Patterns.html#tuple_pattern_element) **,** [*元组模式元素列表*](..\chapter3\07_Patterns.html#tuple_pattern_element_list) > *元组模式元素列表* → [*元组模式元素*](../chapter3/07_Patterns.html#tuple_pattern_element) | [*元组模式元素*](../chapter3/07_Patterns.html#tuple_pattern_element) **,** [*元组模式元素列表*](../chapter3/07_Patterns.html#tuple_pattern_element_list)
> *元组模式元素* → [*模式*](..\chapter3\07_Patterns.html#pattern) > *元组模式元素* → [*模式*](../chapter3/07_Patterns.html#pattern)
<a name="enumeration_case_pattern"></a> <a name="enumeration_case_pattern"></a>
## 枚举用例模式Enumeration Case Pattern ## 枚举用例模式Enumeration Case Pattern
@ -123,7 +127,7 @@ let (a): Int = 2 // a: Int = 2
如果你准备匹配的枚举用例有任何关联的值,则相应的枚举用例模式必须指定一个包含每个关联值元素的元组模式。关于使用`switch`语句来匹配包含关联值枚举用例的例子,请参阅`Associated Values`. 如果你准备匹配的枚举用例有任何关联的值,则相应的枚举用例模式必须指定一个包含每个关联值元素的元组模式。关于使用`switch`语句来匹配包含关联值枚举用例的例子,请参阅`Associated Values`.
> 枚举用例模式语法 > 枚举用例模式语法
> *enum-case-pattern* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) _可选_ **.** [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*元组模式*](..\chapter3\07_Patterns.html#tuple_pattern) _可选_ > *enum-case-pattern* → [*类型标识*](../chapter3/03_Types.html#type_identifier) _可选_ **.** [*枚举的case名*](../chapter3/05_Declarations.html#enum_case_name) [*元组模式*](../chapter3/07_Patterns.html#tuple_pattern) _可选_
<a name="optional_pattern"></a> <a name="optional_pattern"></a>
## 可选模式Optional Pattern ## 可选模式Optional Pattern
@ -158,7 +162,7 @@ for case let number? in arrayOfOptinalInts {
``` ```
> 可选模式语法 > 可选模式语法
> *可选模式* → [*标识符模式*](..\chapter3\03_Types.html#type_identifier) ? > *可选模式* → [*标识符模式*](../chapter3/03_Types.html#type_identifier) ?
<a name="type-casting_patterns"></a> <a name="type-casting_patterns"></a>
## 类型转换模式Type-Casting Patterns ## 类型转换模式Type-Casting Patterns
@ -175,9 +179,9 @@ for case let number? in arrayOfOptinalInts {
关于使用`switch`语句来匹配`is`模式和`as`模式值的例子,请参阅`Type Casting for Any and AnyObject` 关于使用`switch`语句来匹配`is`模式和`as`模式值的例子,请参阅`Type Casting for Any and AnyObject`
> 类型转换模式语法 > 类型转换模式语法
> *type-casting-pattern* → [*is模式*](..\chapter3\07_Patterns.html#is_pattern) | [*as模式*](..\chapter3\07_Patterns.html#as_pattern) > *type-casting-pattern* → [*is模式*](../chapter3/07_Patterns.html#is_pattern) | [*as模式*](../chapter3/07_Patterns.html#as_pattern)
> *is模式* → **is** [*类型*](..\chapter3\03_Types.html#type) > *is模式* → **is** [*类型*](../chapter3/03_Types.html#type)
> *as模式* → [*模式*](..\chapter3\07_Patterns.html#pattern) **as** [*类型*](..\chapter3\03_Types.html#type) > *as模式* → [*模式*](../chapter3/07_Patterns.html#pattern) **as** [*类型*](../chapter3/03_Types.html#type)
<a name="expression_pattern"></a> <a name="expression_pattern"></a>
## 表达式模式Expression Pattern ## 表达式模式Expression Pattern
@ -216,4 +220,4 @@ default:
``` ```
> 表达式模式语法 > 表达式模式语法
> *表达式模式* → [*表达式*](..\chapter3\04_Expressions.html#expression) > *表达式模式* → [*表达式*](../chapter3/04_Expressions.html#expression)

View File

@ -1,5 +1,9 @@
> 1.0
> 翻译:[fd5788](https://github.com/fd5788) > 翻译:[fd5788](https://github.com/fd5788)
> 校对:[yankuangshi](https://github.com/yankuangshi), [stanzhai](https://github.com/stanzhai), [wardenNScaiyi](https:github.com/wardenNScaiyi) > 校对:[yankuangshi](https://github.com/yankuangshi), [stanzhai](https://github.com/stanzhai)
> 2.0
> 翻译+校对:[wardenNScaiyi](https:github.com/wardenNScaiyi)
# 泛型参数 # 泛型参数
--------- ---------
@ -67,15 +71,15 @@ simpleMax(3.14159, 2.71828) // T被推断出为Double类型
> 泛型形参子句语法 > 泛型形参子句语法
> *泛型参数子句* → **<** [*泛型参数列表*](GenericParametersAndArguments.html#generic_parameter_list) [*约束子句*](GenericParametersAndArguments.html#requirement_clause) _可选_ **>** > *泛型参数子句* → **<** [*泛型参数列表*](GenericParametersAndArguments.html#generic_parameter_list) [*约束子句*](GenericParametersAndArguments.html#requirement_clause) _可选_ **>**
> *泛型参数列表* → [*泛形参数*](GenericParametersAndArguments.html#generic_parameter) | [*泛形参数*](GenericParametersAndArguments.html#generic_parameter) **,** [*泛型参数列表*](GenericParametersAndArguments.html#generic_parameter_list) > *泛型参数列表* → [*泛形参数*](GenericParametersAndArguments.html#generic_parameter) | [*泛形参数*](GenericParametersAndArguments.html#generic_parameter) **,** [*泛型参数列表*](GenericParametersAndArguments.html#generic_parameter_list)
> *泛形参数* → [*类型名称*](..\chapter3\03_Types.html#type_name) > *泛形参数* → [*类型名称*](../chapter3/03_Types.html#type_name)
> *泛形参数* → [*类型名称*](..\chapter3\03_Types.html#type_name) **:** [*类型标识*](..\chapter3\03_Types.html#type_identifier) > *泛形参数* → [*类型名称*](../chapter3/03_Types.html#type_name) **:** [*类型标识*](../chapter3/03_Types.html#type_identifier)
> *泛形参数* → [*类型名称*](..\chapter3\03_Types.html#type_name) **:** [*协议合成类型*](..\chapter3\03_Types.html#protocol_composition_type) > *泛形参数* → [*类型名称*](../chapter3/03_Types.html#type_name) **:** [*协议合成类型*](../chapter3/03_Types.html#protocol_composition_type)
> *约束子句* → **where** [*约束列表*](GenericParametersAndArguments.html#requirement_list) > *约束子句* → **where** [*约束列表*](GenericParametersAndArguments.html#requirement_list)
> *约束列表* → [*约束*](GenericParametersAndArguments.html#requirement) | [*约束*](GenericParametersAndArguments.html#requirement) **,** [*约束列表*](GenericParametersAndArguments.html#requirement_list) > *约束列表* → [*约束*](GenericParametersAndArguments.html#requirement) | [*约束*](GenericParametersAndArguments.html#requirement) **,** [*约束列表*](GenericParametersAndArguments.html#requirement_list)
> *约束* → [*一致性约束*](GenericParametersAndArguments.html#conformance_requirement) | [*同类型约束*](GenericParametersAndArguments.html#same_type_requirement) > *约束* → [*一致性约束*](GenericParametersAndArguments.html#conformance_requirement) | [*同类型约束*](GenericParametersAndArguments.html#same_type_requirement)
> *一致性约束* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) **:** [*类型标识*](..\chapter3\03_Types.html#type_identifier) > *一致性约束* → [*类型标识*](../chapter3/03_Types.html#type_identifier) **:** [*类型标识*](../chapter3/03_Types.html#type_identifier)
> *一致性约束* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) **:** [*协议合成类型*](..\chapter3\03_Types.html#protocol_composition_type) > *一致性约束* → [*类型标识*](../chapter3/03_Types.html#type_identifier) **:** [*协议合成类型*](../chapter3/03_Types.html#protocol_composition_type)
> *同类型约束* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) **==** [*类型标识*](..\chapter3\03_Types.html#type_identifier) > *同类型约束* → [*类型标识*](../chapter3/03_Types.html#type_identifier) **==** [*类型标识*](../chapter3/03_Types.html#type_identifier)
<a name="generic_argument"></a> <a name="generic_argument"></a>
@ -109,4 +113,4 @@ let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
> 泛型实参子句语法 > 泛型实参子句语法
> *(泛型参数子句Generic Argument Clause)* → **<** [*泛型参数列表*](GenericParametersAndArguments.html#generic_argument_list) **>** > *(泛型参数子句Generic Argument Clause)* → **<** [*泛型参数列表*](GenericParametersAndArguments.html#generic_argument_list) **>**
> *泛型参数列表* → [*泛型参数*](GenericParametersAndArguments.html#generic_argument) | [*泛型参数*](GenericParametersAndArguments.html#generic_argument) **,** [*泛型参数列表*](GenericParametersAndArguments.html#generic_argument_list) > *泛型参数列表* → [*泛型参数*](GenericParametersAndArguments.html#generic_argument) | [*泛型参数*](GenericParametersAndArguments.html#generic_argument) **,** [*泛型参数列表*](GenericParametersAndArguments.html#generic_argument_list)
> *泛型参数* → [*类型*](..\chapter3\03_Types.html#type) > *泛型参数* → [*类型*](../chapter3/03_Types.html#type)

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,10 @@
> 翻译:[coverxit](https://github.com/coverxit),[littledogboy](https://github.com/littledogboy) > 1.0
> 校对:[numbbbbb](https://github.com/numbbbbb), [coverxit](https://github.com/coverxit), [stanzhai](https://github.com/stanzhai),[littledogboy](https://github.com/littledogboy) > 翻译:[coverxit](https://github.com/coverxit)
> 校对:[numbbbbb](https://github.com/numbbbbb), [coverxit](https://github.com/coverxit), [stanzhai](https://github.com/stanzhai),
> 2.0
> 翻译+校对:[littledogboy](https://github.com/littledogboy)
<a name="statement_statements"></a> <a name="statement_statements"></a>
# 语句 # 语句
----------------- -----------------
@ -19,14 +23,14 @@
是否将分号(`;`)添加到语句的结尾处是可选的。但若要在同一行内写多条独立语句,请务必使用分号。 是否将分号(`;`)添加到语句的结尾处是可选的。但若要在同一行内写多条独立语句,请务必使用分号。
> 语句语法 > 语句语法
> *语句* → [*表达式*](..\chapter3\04_Expressions.html#expression) **;** _可选_ > *语句* → [*表达式*](../chapter3/04_Expressions.html#expression) **;** _可选_
> *语句* → [*声明*](..\chapter3\05_Declarations.html#declaration) **;** _可选_ > *语句* → [*声明*](../chapter3/05_Declarations.html#declaration) **;** _可选_
> *语句* → [*循环语句*](..\chapter3\10_Statements.html#loop_statement) **;** _可选_ > *语句* → [*循环语句*](../chapter3/10_Statements.html#loop_statement) **;** _可选_
> *语句* → [*分支语句*](..\chapter3\10_Statements.html#branch_statement) **;** _可选_ > *语句* → [*分支语句*](../chapter3/10_Statements.html#branch_statement) **;** _可选_
> *语句* → [*标记语句(Labeled Statement)*](..\chapter3\10_Statements.html#labeled_statement) > *语句* → [*标记语句(Labeled Statement)*](../chapter3/10_Statements.html#labeled_statement)
> *语句* → [*控制转移语句*](..\chapter3\10_Statements.html#control_transfer_statement) **;** _可选_ > *语句* → [*控制转移语句*](../chapter3/10_Statements.html#control_transfer_statement) **;** _可选_
> *语句* → [*XXX语句*](..\chapter3\10_Statements.html#control_transfer_statement) **;** _可选_ > *语句* → [*XXX语句*](../chapter3/10_Statements.html#control_transfer_statement) **;** _可选_
> *多条语句(Statements)* → [*语句*](..\chapter3\10_Statements.html#statement) [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements) _可选_ > *多条语句(Statements)* → [*语句*](../chapter3/10_Statements.html#statement) [*多条语句(Statements)*](../chapter3/10_Statements.html#statements) _可选_
<a name="loop_statements"></a> <a name="loop_statements"></a>
## 循环语句 ## 循环语句
@ -36,11 +40,11 @@
通过`break`语句和`continue`语句可以改变循环语句的控制流。有关这两条语句,详情参见 [Break 语句](#break_statement)和 [Continue 语句](#continue_statement)。 通过`break`语句和`continue`语句可以改变循环语句的控制流。有关这两条语句,详情参见 [Break 语句](#break_statement)和 [Continue 语句](#continue_statement)。
> 循环语句语法 > 循环语句语法
> *循环语句* → [*for语句*](..\chapter3\10_Statements.html#for_statement) > *循环语句* → [*for语句*](../chapter3/10_Statements.html#for_statement)
> *循环语句* → [*for-in语句*](..\chapter3\10_Statements.html#for_in_statement) > *循环语句* → [*for-in语句*](../chapter3/10_Statements.html#for_in_statement)
> *循环语句* → [*while语句*](..\chapter3\10_Statements.html#wheetatype类型ile_statement) > *循环语句* → [*while语句*](../chapter3/10_Statements.html#wheetatype类型ile_statement)
> *循环语句* → [*do-while语句*](..\chapter3\10_Statements.html#do_while_statement) > *循环语句* → [*do-while语句*](../chapter3/10_Statements.html#do_while_statement)
<a name="for_statements"></a> <a name="for_statements"></a>
### For 语句 ### For 语句
@ -64,11 +68,11 @@
*initialzation* 中定义的变量仅在`for`循环的作用域内有效。*condition* 表达式的值的类型必须遵循`BooleanType `协议。 *initialzation* 中定义的变量仅在`for`循环的作用域内有效。*condition* 表达式的值的类型必须遵循`BooleanType `协议。
> For 循环语法 > For 循环语法
> *for语句* → **for** [*for初始条件*](..\chapter3\10_Statements.html#for_init) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block) > *for语句* → **for** [*for初始条件*](../chapter3/10_Statements.html#for_init) _可选_ **;** [*表达式*](../chapter3/04_Expressions.html#expression) _可选_ **;** [*表达式*](../chapter3/04_Expressions.html#expression) _可选_ [*代码块*](../chapter3/05_Declarations.html#code_block)
> *for语句* → **for** **(** [*for初始条件*](..\chapter3\10_Statements.html#for_init) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ **)** [*代码块*](..\chapter3\05_Declarations.html#code_block) > *for语句* → **for** **(** [*for初始条件*](../chapter3/10_Statements.html#for_init) _可选_ **;** [*表达式*](../chapter3/04_Expressions.html#expression) _可选_ **;** [*表达式*](../chapter3/04_Expressions.html#expression) _可选_ **)** [*代码块*](../chapter3/05_Declarations.html#code_block)
> *for初始条件* → [*变量声明*](..\chapter3\05_Declarations.html#variable_declaration) | [*表达式列表*](..\chapter3\04_Expressions.html#expression_list) > *for初始条件* → [*变量声明*](../chapter3/05_Declarations.html#variable_declaration) | [*表达式列表*](../chapter3/04_Expressions.html#expression_list)
<a name="for-in_statements"></a> <a name="for-in_statements"></a>
### For-In 语句 ### For-In 语句
@ -83,9 +87,9 @@
`for-in`语句在循环开始前会调用 *collection* 表达式的`generate`方法来获取一个生成器类型(这是一个遵循`Generator`协议的类型)的值。接下来循环开始,调用 *collection* 表达式的`next`方法。如果其返回值不是`None`,它将会被赋给 *item*,然后执行 *statements*,执行完毕后回到循环开始处;否则,将不会赋值给 *item* 也不会执行 *statements*`for-in`至此执行完毕。 `for-in`语句在循环开始前会调用 *collection* 表达式的`generate`方法来获取一个生成器类型(这是一个遵循`Generator`协议的类型)的值。接下来循环开始,调用 *collection* 表达式的`next`方法。如果其返回值不是`None`,它将会被赋给 *item*,然后执行 *statements*,执行完毕后回到循环开始处;否则,将不会赋值给 *item* 也不会执行 *statements*`for-in`至此执行完毕。
> For-In 循环语法 > For-In 循环语法
> *for-in语句* → **for** [*模式*](..\chapter3\07_Patterns.html#pattern) **in** [*表达式*](..\chapter3\04_Expressions.html#expression) [*代码块*](..\chapter3\05_Declarations.html#code_block) > *for-in语句* → **for** [*模式*](../chapter3/07_Patterns.html#pattern) **in** [*表达式*](../chapter3/04_Expressions.html#expression) [*代码块*](../chapter3/05_Declarations.html#code_block)
<a name="while_statements"></a> <a name="while_statements"></a>
### While 语句 ### While 语句
@ -108,21 +112,21 @@
*condition* 表达式的值的类型必须遵循`BooleanType `协议。同时,*condition* 表达式也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。 *condition* 表达式的值的类型必须遵循`BooleanType `协议。同时,*condition* 表达式也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
> While 循环语法 > While 循环语法
> *while语句* → **while** [*while条件*](..\chapter3\10_Statements.html#while_condition) [*代码块*](..\chapter3\05_Declarations.html#code_block) > *while语句* → **while** [*while条件*](../chapter3/10_Statements.html#while_condition) [*代码块*](../chapter3/05_Declarations.html#code_block)
> *条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*声明*](..\chapter3\05_Declarations.html#declaration) > *条件* → [*表达式*](../chapter3/04_Expressions.html#expression) | [*声明*](../chapter3/05_Declarations.html#declaration)
> *条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) > *条件* → [*表达式*](../chapter3/04_Expressions.html#expression)
> *条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*条件列表*](TODO) > *条件* → [*表达式*](../chapter3/04_Expressions.html#expression) | [*条件列表*](TODO)
> *条件* → [*可用条件*](..\chapter3\10_Statement.html#availability) [*表达式*](..\chapter3\04_Expressions.html#expression) > *条件* → [*可用条件*](../chapter3/10_Statement.html#availability) [*表达式*](../chapter3/04_Expressions.html#expression)
> *条件列表* → [*条件条件*](TODO) [*条件列表*](TODO) > *条件列表* → [*条件条件*](TODO) [*条件列表*](TODO)
> *条件* → [*可用条件*](..\chapter3\10_Statement.html#availability) [可选绑定条件](../chapter2/01_The_Basics.html#optional_binding) > *条件* → [*可用条件*](../chapter3/10_Statement.html#availability) [可选绑定条件](../chapter2/01_The_Basics.html#optional_binding)
> *case条件* → **case** [*模式*](..\chapter3\07_Patterns.html#pattern) [构造器](TODO) [where](DOTO) > *case条件* → **case** [*模式*](../chapter3/07_Patterns.html#pattern) [构造器](TODO) [where](DOTO)
> *可选绑定条件* → [可选绑定头](TODO) [持续可选绑定](TODO) [持续可选绑定列表](TODO) > *可选绑定条件* → [可选绑定头](TODO) [持续可选绑定](TODO) [持续可选绑定列表](TODO)
> *可选绑定头* → **let** [*模式*](..\chapter3\07_Patterns.html#pattern) [构造器](TODO) **var** [*模式*](..\chapter3\07_Patterns.html#pattern) [构造器](TODO) > *可选绑定头* → **let** [*模式*](../chapter3/07_Patterns.html#pattern) [构造器](TODO) **var** [*模式*](../chapter3/07_Patterns.html#pattern) [构造器](TODO)
> *可持续绑定列表* → [*模式*](..\chapter3\07_Patterns.html#pattern) | [构造器](TODO) [可选绑定头](TODO) > *可持续绑定列表* → [*模式*](../chapter3/07_Patterns.html#pattern) | [构造器](TODO) [可选绑定头](TODO)
> >
<a name="while-while_statements"></a> <a name="while-while_statements"></a>
### Repeat-While 语句 ### Repeat-While 语句
@ -145,7 +149,7 @@
*condition* 表达式的值的类型必须遵循`BooleanType `协议。同时,*condition* 表达式也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。 *condition* 表达式的值的类型必须遵循`BooleanType `协议。同时,*condition* 表达式也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
> Repeat-While 循环语法 > Repeat-While 循环语法
> * repeat-while语句* → **repeat** [*代码块*](..\chapter3\05_Declarations.html#code_block) **while** [*while条件*](..\chapter3\10_Statements.html#while_condition) > * repeat-while语句* → **repeat** [*代码块*](../chapter3/05_Declarations.html#code_block) **while** [*while条件*](../chapter3/10_Statements.html#while_condition)
<a name="branch_statements"></a> <a name="branch_statements"></a>
## 分支语句 ## 分支语句
@ -155,10 +159,10 @@
`switch`语句中的控制流可以用`break`语句修改,详情请见[Break 语句](#break_statement)。 `switch`语句中的控制流可以用`break`语句修改,详情请见[Break 语句](#break_statement)。
> 分支语句语法 > 分支语句语法
> *分支语句* → [*if语句*](..\chapter3\10_Statements.html#if_statement) > *分支语句* → [*if语句*](../chapter3/10_Statements.html#if_statement)
> *分支语句* → [*switch语句*](..\chapter3\10_Statements.html#switch_statement) > *分支语句* → [*switch语句*](../chapter3/10_Statements.html#switch_statement)
<a name="if_statements"></a> <a name="if_statements"></a>
### If 语句 ### If 语句
@ -194,34 +198,34 @@
`if`语句中条件的值的类型必须遵循`LogicValue`协议。同时,条件也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。 `if`语句中条件的值的类型必须遵循`LogicValue`协议。同时,条件也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
> If语句语法 > If语句语法
> *if语句* → **if** [*if条件*](..\chapter3\10_Statements.html#if_condition) [*代码块*](..\chapter3\05_Declarations.html#code_block) [*else(Clause)*](..\chapter3\10_Statements.html#else_clause) _可选_ > *if语句* → **if** [*if条件*](../chapter3/10_Statements.html#if_condition) [*代码块*](../chapter3/05_Declarations.html#code_block) [*else(Clause)*](../chapter3/10_Statements.html#else_clause) _可选_
> *if条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*声明*](..\chapter3\05_Declarations.html#declaration) > *if条件* → [*表达式*](../chapter3/04_Expressions.html#expression) | [*声明*](../chapter3/05_Declarations.html#declaration)
> *else(Clause)* → **else** [*代码块*](..\chapter3\05_Declarations.html#code_block) | **else** [*if语句*](..\chapter3\10_Statements.html#if_statement) > *else(Clause)* → **else** [*代码块*](../chapter3/05_Declarations.html#code_block) | **else** [*if语句*](../chapter3/10_Statements.html#if_statement)
<a name="guard_statements"></a> <a name="guard_statements"></a>
### Guard 语句 ### Guard 语句
`guard` 语句用来转移程序控制出其作用域,如果一个或者多个条件不成立。 `guard` 语句用来转移程序控制出其作用域,如果一个或者多个条件不成立。
`guard` 语句的格式如下: `guard` 语句的格式如下:
> guard `condition` else { > guard `condition` else {
`statements` `statements`
>} >}
`guard`语句中条件值的类型必须遵循`LogicValue`协议。且条件可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。 `guard`语句中条件值的类型必须遵循`LogicValue`协议。且条件可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
`guard`语句中声明的常量或者变量,可用范围从声明开始到作用域结束,常量和变量的值从可选绑定声明中分配。 `guard`语句中声明的常量或者变量,可用范围从声明开始到作用域结束,常量和变量的值从可选绑定声明中分配。
`guard`语句需要有`else`子句,并且必须调用被`noreturn`属性标记的函数,或者使用下面的语句把程序执行转移到guard语句的作用域外。 `guard`语句需要有`else`子句,并且必须调用被`noreturn`属性标记的函数,或者使用下面的语句把程序执行转移到guard语句的作用域外。
* `return` * `return`
* `break` * `break`
* `continue` * `continue`
* `throw` * `throw`
执行转移语句详情参见[控制传递语句](TODO) 执行转移语句详情参见[控制传递语句](TODO)
<a name="switch_statements"></a> <a name="switch_statements"></a>
### Switch 语句 ### Switch 语句
@ -266,18 +270,18 @@ case let (x, y) where x == y:
当匹配的 case 分支中的代码执行完毕后,程序会终止`switch`语句,而不会继续执行下一个 case 分支。这就意味着,如果你想执行下一个 case 分支,需要显式地在你需要的 case 分支里使用`fallthrough`语句。关于`fallthrough`语句的更多信息,详情参见 [Fallthrough 语句](#fallthrough_statement)。 当匹配的 case 分支中的代码执行完毕后,程序会终止`switch`语句,而不会继续执行下一个 case 分支。这就意味着,如果你想执行下一个 case 分支,需要显式地在你需要的 case 分支里使用`fallthrough`语句。关于`fallthrough`语句的更多信息,详情参见 [Fallthrough 语句](#fallthrough_statement)。
> Switch语句语法 > Switch语句语法
> *switch语句* → **switch** [*表达式*](..\chapter3\04_Expressions.html#expression) **{** [*SwitchCase列表*](..\chapter3\10_Statements.html#switch_cases) _可选_ **}** > *switch语句* → **switch** [*表达式*](../chapter3/04_Expressions.html#expression) **{** [*SwitchCase列表*](../chapter3/10_Statements.html#switch_cases) _可选_ **}**
> *SwitchCase列表* → [*SwitchCase*](..\chapter3\10_Statements.html#switch_case) [*SwitchCase列表*](..\chapter3\10_Statements.html#switch_cases) _可选_ > *SwitchCase列表* → [*SwitchCase*](../chapter3/10_Statements.html#switch_case) [*SwitchCase列表*](../chapter3/10_Statements.html#switch_cases) _可选_
> *SwitchCase* → [*case标签*](..\chapter3\10_Statements.html#case_label) [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements) | [*default标签*](..\chapter3\10_Statements.html#default_label) [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements) > *SwitchCase* → [*case标签*](../chapter3/10_Statements.html#case_label) [*多条语句(Statements)*](../chapter3/10_Statements.html#statements) | [*default标签*](../chapter3/10_Statements.html#default_label) [*多条语句(Statements)*](../chapter3/10_Statements.html#statements)
> *SwitchCase* → [*case标签*](..\chapter3\10_Statements.html#case_label) **;** | [*default标签*](..\chapter3\10_Statements.html#default_label) **;** > *SwitchCase* → [*case标签*](../chapter3/10_Statements.html#case_label) **;** | [*default标签*](../chapter3/10_Statements.html#default_label) **;**
> *case标签* → **case** [*case项列表*](..\chapter3\10_Statements.html#case_item_list) **:** > *case标签* → **case** [*case项列表*](../chapter3/10_Statements.html#case_item_list) **:**
> *case项列表* → [*模式*](..\chapter3\07_Patterns.html#pattern) [*guard-clause*](..\chapter3\10_Statements.html#guard_clause) _可选_ | [*模式*](..\chapter3\07_Patterns.html#pattern) [*guard-clause*](..\chapter3\10_Statements.html#guard_clause) _可选_ **,** [*case项列表*](..\chapter3\10_Statements.html#case_item_list) > *case项列表* → [*模式*](../chapter3/07_Patterns.html#pattern) [*guard-clause*](../chapter3/10_Statements.html#guard_clause) _可选_ | [*模式*](../chapter3/07_Patterns.html#pattern) [*guard-clause*](../chapter3/10_Statements.html#guard_clause) _可选_ **,** [*case项列表*](../chapter3/10_Statements.html#case_item_list)
> *default标签* → **default** **:** > *default标签* → **default** **:**
> *where-clause* → **where** [*guard-expression*](..\chapter3\10_Statements.html#guard) > *where-clause* → **where** [*guard-expression*](../chapter3/10_Statements.html#guard)
> *where-expression* → [*表达式*](..\chapter3\04_Expressions.html#expression) > *where-expression* → [*表达式*](../chapter3/04_Expressions.html#expression)
<a name="labeled_statements"></a> <a name="labeled_statements"></a>
<a name="control_transfer_statements"></a> <a name="control_transfer_statements"></a>
## 带标签的语句 ## 带标签的语句
你可以在循环语句或`switch`语句前面加上*标签*,它由标签名和紧随其后的冒号(:)组成。在`break``continue`后面跟上标签名可以显式地在循环语句或`switch`语句中更改控制流,把控制权传递给指定标签标记的语句。关于这两条语句用法,详情参见 [Break 语句](#break_statement)和 [Continue 语句](#continue_statement)。 你可以在循环语句或`switch`语句前面加上*标签*,它由标签名和紧随其后的冒号(:)组成。在`break``continue`后面跟上标签名可以显式地在循环语句或`switch`语句中更改控制流,把控制权传递给指定标签标记的语句。关于这两条语句用法,详情参见 [Break 语句](#break_statement)和 [Continue 语句](#continue_statement)。
@ -287,21 +291,21 @@ case let (x, y) where x == y:
关于使用带标签的语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的[带标签的语句](../chapter2/05_Control_Flow.html#labeled_statements)。 关于使用带标签的语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的[带标签的语句](../chapter2/05_Control_Flow.html#labeled_statements)。
> 标记语句语法 > 标记语句语法
> *标记语句(Labeled Statement)* → [*语句标签*](..\chapter3\10_Statements.html#statement_label) [*循环语句*](..\chapter3\10_Statements.html#loop_statement) | [*语句标签*](..\chapter3\10_Statements.html#statement_label) [*switch语句*](..\chapter3\10_Statements.html#switch_statement) > *标记语句(Labeled Statement)* → [*语句标签*](../chapter3/10_Statements.html#statement_label) [*循环语句*](../chapter3/10_Statements.html#loop_statement) | [*语句标签*](../chapter3/10_Statements.html#statement_label) [*switch语句*](../chapter3/10_Statements.html#switch_statement)
> *语句标签* → [*标签名称*](..\chapter3\10_Statements.html#label_name) **:** > *语句标签* → [*标签名称*](../chapter3/10_Statements.html#label_name) **:**
> *标签名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) > *标签名称* → [*标识符*](../chapter3/02_Lexical_Structure.html#identifier)
<a name="control_transfer_statements"></a> <a name="control_transfer_statements"></a>
## 控制传递语句 ## 控制传递语句
通过无条件地把控制权从一片代码传递到另一片代码控制传递语句能够改变代码执行的顺序。Swift 提供四种类型的控制传递语句:`break`语句、`continue`语句、`fallthrough`语句和`return`语句。 通过无条件地把控制权从一片代码传递到另一片代码控制传递语句能够改变代码执行的顺序。Swift 提供四种类型的控制传递语句:`break`语句、`continue`语句、`fallthrough`语句和`return`语句。
> 控制传递语句(Control Transfer Statement) 语法 > 控制传递语句(Control Transfer Statement) 语法
> *控制传递语句* → [*break语句*](..\chapter3\10_Statements.html#break_statement) > *控制传递语句* → [*break语句*](../chapter3/10_Statements.html#break_statement)
> *控制传递语句* → [*continue语句*](..\chapter3\10_Statements.html#continue_statement) > *控制传递语句* → [*continue语句*](../chapter3/10_Statements.html#continue_statement)
> *控制传递语句* → [*fallthrough语句*](..\chapter3\10_Statements.html#fallthrough_statement) > *控制传递语句* → [*fallthrough语句*](../chapter3/10_Statements.html#fallthrough_statement)
> *控制传递语句* → [*return语句*](..\chapter3\10_Statements.html#return_statement) > *控制传递语句* → [*return语句*](../chapter3/10_Statements.html#return_statement)
> *控制传递语句* → [*throw语句*](..\chapter3\10_Statements.html#throw_statement) > *控制传递语句* → [*throw语句*](../chapter3/10_Statements.html#throw_statement)
<a name="break_statements"></a> <a name="break_statements"></a>
### Break 语句 ### Break 语句
@ -320,7 +324,7 @@ case let (x, y) where x == y:
关于使用`break`语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的 [Break](../chapter2/05_Control_Flow.html#break) 和[带标签的语句](../chapter2/05_Control_Flow.html#labeled_statements)。 关于使用`break`语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的 [Break](../chapter2/05_Control_Flow.html#break) 和[带标签的语句](../chapter2/05_Control_Flow.html#labeled_statements)。
> Break 语句语法 > Break 语句语法
> *break语句* → **break** [*标签名称*](..\chapter3\10_Statements.html#label_name) _可选_ > *break语句* → **break** [*标签名称*](../chapter3/10_Statements.html#label_name) _可选_
<a name="continue_statements"></a> <a name="continue_statements"></a>
### Continue 语句 ### Continue 语句
@ -341,7 +345,7 @@ case let (x, y) where x == y:
关于使用`continue`语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的 [Continue](../chapter2/05_Control_Flow.html#continue) 和[带标签的语句](../chapter2/05_Control_Flow.html#labeled_statements)。 关于使用`continue`语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的 [Continue](../chapter2/05_Control_Flow.html#continue) 和[带标签的语句](../chapter2/05_Control_Flow.html#labeled_statements)。
> Continue 语句语法 > Continue 语句语法
> *continue语句* → **continue** [*标签名称*](..\chapter3\10_Statements.html#label_name) _可选_ > *continue语句* → **continue** [*标签名称*](../chapter3/10_Statements.html#label_name) _可选_
<a name="fallthrough_statements"></a> <a name="fallthrough_statements"></a>
### Fallthrough 语句 ### Fallthrough 语句
@ -353,7 +357,7 @@ case let (x, y) where x == y:
关于在`switch`语句中使用`fallthrough`语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的[控制传递语句](../chapter2/05_Control_Flow.html#control_transfer_statements)。 关于在`switch`语句中使用`fallthrough`语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的[控制传递语句](../chapter2/05_Control_Flow.html#control_transfer_statements)。
> Fallthrough 语句语法 > Fallthrough 语句语法
> *fallthrough语句* → **fallthrough** > *fallthrough语句* → **fallthrough**
<a name="return_statements"></a> <a name="return_statements"></a>
### Return 语句 ### Return 语句
@ -370,125 +374,125 @@ case let (x, y) where x == y:
而当只写`return`时,仅仅是将控制权从该函数或方法传递给调用者,而不返回一个值。(这就是说,该函数或方法的返回类型为`Void``()` 而当只写`return`时,仅仅是将控制权从该函数或方法传递给调用者,而不返回一个值。(这就是说,该函数或方法的返回类型为`Void``()`
> Return 语句语法 > Return 语句语法
> *return语句* → **return** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ > *return语句* → **return** [*表达式*](../chapter3/04_Expressions.html#expression) _可选_
<a name="availability_statements"></a> <a name="availability_statements"></a>
### Availability 语句 ### Availability 语句
可用性条件,被当做`if` `while` 语句的条件,并且 `guard` 语句在运行时会基于特定的语法格式查询接口的可用性。 可用性条件,被当做`if` `while` 语句的条件,并且 `guard` 语句在运行时会基于特定的语法格式查询接口的可用性。
avaliability 语句的形式如下: avaliability 语句的形式如下:
> if #available(`platform name version`,` ...`, *) { > if #available(`platform name version`,` ...`, *) {
> `statements to execute if the APIs are available` > `statements to execute if the APIs are available`
> } else { > } else {
> `fallback statements to execute if the APIs are unavailable` > `fallback statements to execute if the APIs are unavailable`
> } > }
可用性条件执行一个代码块时,取决于在运行时想要使用的接口是否可用。 可用性条件执行一个代码块时,取决于在运行时想要使用的接口是否可用。
当编译器检查到代码块中的接口是可用的,则从可用性条件中获取相应信息。 当编译器检查到代码块中的接口是可用的,则从可用性条件中获取相应信息。
可用性条件使用逗号分隔平台名称和版本列表。使用`iOS``OSX`,以及`watchOS`为平台名称,包括相应的版本号。*参数是必需的。在任何平台上代码块主体都被可用性条件保护起来,由满足最低部署条件的目标设备运行。 可用性条件使用逗号分隔平台名称和版本列表。使用`iOS``OSX`,以及`watchOS`为平台名称,包括相应的版本号。*参数是必需的。在任何平台上代码块主体都被可用性条件保护起来,由满足最低部署条件的目标设备运行。
与布尔类型条件不同,不能用逻辑运算符 **&&** 和 **||** 合并可用性条件。 与布尔类型条件不同,不能用逻辑运算符 **&&** 和 **||** 合并可用性条件。
> 可用性条件语法 > 可用性条件语法
> *可用性条件* → **#available** ( [availability-arguments­](TODO) ) > *可用性条件* → **#available** ( [availability-arguments­](TODO) )
> *可用性条件* → [availability-argument­](TODO) | [availability-argument](TODO)­ ,­ [availability-arguments­](TODO) > *可用性条件* → [availability-argument­](TODO) | [availability-argument](TODO)­ ,­ [availability-arguments­](TODO)
> *可用性条件* → [平台名称](TODO) [版本号](TODO) > *可用性条件* → [平台名称](TODO) [版本号](TODO)
> *可用性条件* → **\*** > *可用性条件* → **\***
> *平台名称* → **iOS** | **iOSApplicationExtension** > *平台名称* → **iOS** | **iOSApplicationExtension**
> *平台名称* → **OSX** | **OSXApplicationExtension­** > *平台名称* → **OSX** | **OSXApplicationExtension­**
> *平台名称* → **watchOS** > *平台名称* → **watchOS**
> *版本号* → [十进制数字](TODO) > *版本号* → [十进制数字](TODO)
> *版本号* → [十进制数字](TODO) **.** [十进制数字](TODO) > *版本号* → [十进制数字](TODO) **.** [十进制数字](TODO)
> *版本号* → [十进制数字](TODO) **.** [十进制数字](TODO) **.** [十进制数字](TODO) > *版本号* → [十进制数字](TODO) **.** [十进制数字](TODO) **.** [十进制数字](TODO)
<a name="throw_statements"></a> <a name="throw_statements"></a>
### Throw 语句 ### Throw 语句
`throw`语句出现在抛出函数或者抛出方法体内,或者类型被`throws`关键字标记的表达式体内。 `throw`语句出现在抛出函数或者抛出方法体内,或者类型被`throws`关键字标记的表达式体内。
`throw`语句使程序结束执行当前的作用域,并在封闭作用域中传播错误。抛出的错误会一直传播,直到被`do`语句的`catch`子句处理掉。 `throw`语句使程序结束执行当前的作用域,并在封闭作用域中传播错误。抛出的错误会一直传播,直到被`do`语句的`catch`子句处理掉。
`throw`语句由`throw`关键字 跟一个表达式组成 ,如下所示。 `throw`语句由`throw`关键字 跟一个表达式组成 ,如下所示。
> throw `expression` > throw `expression`
表达式值的类型必须遵循 `LogicValue`协议 表达式值的类型必须遵循 `LogicValue`协议
关于如何使用`throw`语句的例子,详情参见[错误处理](TODO)一章的[抛出错误](TODO)。 关于如何使用`throw`语句的例子,详情参见[错误处理](TODO)一章的[抛出错误](TODO)。
> throw 语句语法 > throw 语句语法
> *抛出语句* → **throw** *[表达式­](TODO)* > *抛出语句* → **throw** *[表达式­](TODO)*
<a name="defer_statements"></a> <a name="defer_statements"></a>
### Defer 语句 ### Defer 语句
`defer` 语句用于转移程序控制出延迟语句作用域之前执行代码。 `defer` 语句用于转移程序控制出延迟语句作用域之前执行代码。
`defer` 语句中的语句无论程序控制如何转移都会执行。这意味着 `defer` 语句可以被使用在以下这些情况,像手动得执行资源管理,关闭文件描述,或者即使抛出了错误也需要去实现执行一些动作。 `defer` 语句中的语句无论程序控制如何转移都会执行。这意味着 `defer` 语句可以被使用在以下这些情况,像手动得执行资源管理,关闭文件描述,或者即使抛出了错误也需要去实现执行一些动作。
如果多个 `defer` 语句出现在同一范围内,那么它们执行的顺序与出现的顺序相反。给定作用域中的第一个`defer` 语句,会在最后执行,这意味着最后执行的延迟语句中的语句涉及的资源可以被其他 `defer`语句清理掉。 如果多个 `defer` 语句出现在同一范围内,那么它们执行的顺序与出现的顺序相反。给定作用域中的第一个`defer` 语句,会在最后执行,这意味着最后执行的延迟语句中的语句涉及的资源可以被其他 `defer`语句清理掉。
> 1 func f( ) { > 1 func f( ) {
> 2 defer { print("First") } > 2 defer { print("First") }
> 3 defer { print("Second") } > 3 defer { print("Second") }
> 4 defer { print("Third") } > 4 defer { print("Third") }
> 5 } > 5 }
> 6 f() > 6 f()
> 7 // prints "Third" > 7 // prints "Third"
> 8 // prints "Second" > 8 // prints "Second"
> 9 // prints "First" > 9 // prints "First"
`defer` 语句中的语句无法转移程序控制出延迟语句。 `defer` 语句中的语句无法转移程序控制出延迟语句。
> defer 语句语法 > defer 语句语法
> *延迟语句* → **defer** *[代码块](TODO)* > *延迟语句* → **defer** *[代码块](TODO)*
<a name="do_statements"></a> <a name="do_statements"></a>
### Do 语句 ### Do 语句
`do` 语句用于引入一个新的作用域,该作用域中可以含有一个或多个`catch`子句,catch子句中定义了一些匹配错误情况的模式。`do` 语句作用域内定义的常量和变量只能在do语句作用域内访问。 `do` 语句用于引入一个新的作用域,该作用域中可以含有一个或多个`catch`子句,catch子句中定义了一些匹配错误情况的模式。`do` 语句作用域内定义的常量和变量只能在do语句作用域内访问。
swift 中的 do 语句与C 中限定代码块界限的大括号 {})很相似,并且在程序运行的时候并不会造成系统开销。 swift 中的 do 语句与C 中限定代码块界限的大括号 {})很相似,并且在程序运行的时候并不会造成系统开销。
> do { > do {
> try `expression` > try `expression`
> `statements` > `statements`
> } catch `pattern 1` { > } catch `pattern 1` {
`statements` `statements`
> } catch `pattern 2` where condition { > } catch `pattern 2` where condition {
`statements` `statements`
> } > }
如同`switch`语句,编译器会判断`catch`子句是否被遗漏。如果catch没有被遗漏则认为错误被处理。否则错误会自动传播出包含作用域,被一个封闭的`catch`语句或抛出函数处理掉,包含函数必须以`throws`关键字声明。 如同`switch`语句,编译器会判断`catch`子句是否被遗漏。如果catch没有被遗漏则认为错误被处理。否则错误会自动传播出包含作用域,被一个封闭的`catch`语句或抛出函数处理掉,包含函数必须以`throws`关键字声明。
为了确保错误已经被处理,使用一个匹配所有错误的`catch`子句如通配符模式_。如果一个`catch`子句不指定一种模式,`catch`子句会匹配和约束任何局部变量命名的`error`。有关在`catch`子句中使用模式的更多信息,详见[模式](TODO)。 为了确保错误已经被处理,使用一个匹配所有错误的`catch`子句如通配符模式_。如果一个`catch`子句不指定一种模式,`catch`子句会匹配和约束任何局部变量命名的`error`。有关在`catch`子句中使用模式的更多信息,详见[模式](TODO)。
关于在一些`catch`子句中如何使用` do`语句的例子,详情参见[错误处理](TODO)一章的[抛出错误](TODO)。 关于在一些`catch`子句中如何使用` do`语句的例子,详情参见[错误处理](TODO)一章的[抛出错误](TODO)。
> do 语句语法 → **do** *[*代码块*](..\chapter3\05_Declarations.html#code_block) [catch](TODO)* > do 语句语法 → **do** *[*代码块*](../chapter3/05_Declarations.html#code_block) [catch](TODO)*
> catch → *[catch子句](TODO) [catch子句](TODO)* > catch → *[catch子句](TODO) [catch子句](TODO)*
> catch → **catch** *[*模式*](..\chapter3\07_Patterns.html#pattern)** *可选的* [*where*]() *可选的* [*代码块*](..\chapter3\05_Declarations.html#code_block) > catch → **catch** *[*模式*](../chapter3/07_Patterns.html#pattern)** *可选的* [*where*]() *可选的* [*代码块*](../chapter3/05_Declarations.html#code_block)