fix relative links

This commit is contained in:
Jie Liang
2019-03-26 22:08:00 -05:00
parent adc4897eff
commit 7eb0b94d85
23 changed files with 86 additions and 86 deletions

View File

@ -14,7 +14,7 @@
* [函数](chapter2/06_Functions.md) * [函数](chapter2/06_Functions.md)
* [闭包](chapter2/07_Closures.md) * [闭包](chapter2/07_Closures.md)
* [枚举](chapter2/08_Enumerations.md) * [枚举](chapter2/08_Enumerations.md)
* [类和结构体](chapter2/09_Classes_and_Structures.md) * [类和结构体](chapter2/09_Structures_And_Classes.md)
* [属性](chapter2/10_Properties.md) * [属性](chapter2/10_Properties.md)
* [方法](chapter2/11_Methods.md) * [方法](chapter2/11_Methods.md)
* [下标](chapter2/12_Subscripts.md) * [下标](chapter2/12_Subscripts.md)

View File

@ -3,7 +3,7 @@
Swift 是一门开发 iOS, macOS, watchOS 和 tvOS 应用的新语言。然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 Swift 的很多内容都是你熟悉的。 Swift 是一门开发 iOS, macOS, watchOS 和 tvOS 应用的新语言。然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 Swift 的很多内容都是你熟悉的。
Swift 包含了 C 和 Objective-C 上所有基础数据类型,`Int` 表示整型值; `Double``Float` 表示浮点型值; `Bool` 是布尔型值;`String` 是文本型数据。 Swift 还提供了三个基本的集合类型,`Array``Set``Dictionary` ,详见[集合类型](./04_Collection_Types.html)。 Swift 包含了 C 和 Objective-C 上所有基础数据类型,`Int` 表示整型值; `Double``Float` 表示浮点型值; `Bool` 是布尔型值;`String` 是文本型数据。 Swift 还提供了三个基本的集合类型,`Array``Set``Dictionary` ,详见[集合类型](./04_Collection_Types.md)。
就像 C 语言一样Swift 使用变量来进行存储并通过变量名来关联值。在 Swift 中,广泛的使用着值不可变的变量,它们就是常量,而且比 C 语言的常量更强大。在 Swift 中,如果你要处理的值不需要改变,那使用常量可以让你的代码更加安全并且更清晰地表达你的意图。 就像 C 语言一样Swift 使用变量来进行存储并通过变量名来关联值。在 Swift 中,广泛的使用着值不可变的变量,它们就是常量,而且比 C 语言的常量更强大。在 Swift 中,如果你要处理的值不需要改变,那使用常量可以让你的代码更加安全并且更清晰地表达你的意图。
@ -122,7 +122,7 @@ print(friendlyWelcome)
// 输出“Bonjour!” // 输出“Bonjour!”
``` ```
`print(_:separator:terminator:)` 是一个用来输出一个或多个值到适当输出区的全局函数。如果你用 Xcode`print(_:separator:terminator:)` 将会输出内容到“console”面板上。`separator``terminator` 参数具有默认值,因此你调用这个函数的时候可以忽略它们。默认情况下,该函数通过添加换行符来结束当前行。如果不想换行,可以传递一个空字符串给 `terminator` 参数--例如,`print(someValue, terminator:"")` 。关于参数默认值的更多信息,请参考[默认参数值](./06_Functions.html#default_parameter_values)。 `print(_:separator:terminator:)` 是一个用来输出一个或多个值到适当输出区的全局函数。如果你用 Xcode`print(_:separator:terminator:)` 将会输出内容到“console”面板上。`separator``terminator` 参数具有默认值,因此你调用这个函数的时候可以忽略它们。默认情况下,该函数通过添加换行符来结束当前行。如果不想换行,可以传递一个空字符串给 `terminator` 参数--例如,`print(someValue, terminator:"")` 。关于参数默认值的更多信息,请参考[默认参数值](./06_Functions.md#default_parameter_values)。
Swift 用*字符串插值string interpolation*的方式把常量名或者变量名当做占位符加入到长字符串中Swift 会用当前常量或变量的值替换这些占位符。将常量或变量名放入圆括号中,并在开括号前使用反斜杠将其转义: Swift 用*字符串插值string interpolation*的方式把常量名或者变量名当做占位符加入到长字符串中Swift 会用当前常量或变量的值替换这些占位符。将常量或变量名放入圆括号中,并在开括号前使用反斜杠将其转义:
@ -133,7 +133,7 @@ print("The current value of friendlyWelcome is \(friendlyWelcome)")
> 注意 > 注意
> >
> 字符串插值所有可用的选项,请参考[字符串插值](./03_Strings_and_Characters.html#string_interpolation)。 > 字符串插值所有可用的选项,请参考[字符串插值](./03_Strings_and_Characters.md#string_interpolation)。
<a name="comments"></a> <a name="comments"></a>
## 注释 ## 注释
@ -344,7 +344,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.md)。
<a name="integer_and_floating_point_conversion"></a> <a name="integer_and_floating_point_conversion"></a>
### 整数和浮点数转换 ### 整数和浮点数转换
@ -416,7 +416,7 @@ if turnipsAreDelicious {
// 输出“Eww, turnips are horrible.” // 输出“Eww, turnips are horrible.”
``` ```
条件语句,例如 `if`,请参考[控制流](./05_Control_Flow.html)。 条件语句,例如 `if`,请参考[控制流](./05_Control_Flow.md)。
如果你在需要使用 `Bool` 类型的地方使用了非布尔值Swift 的类型安全机制会报错。下面的例子会报告一个编译时错误: 如果你在需要使用 `Bool` 类型的地方使用了非布尔值Swift 的类型安全机制会报错。下面的例子会报告一个编译时错误:
@ -436,7 +436,7 @@ if i == 1 {
} }
``` ```
`i == 1` 的比较结果是 `Bool` 类型,所以第二个例子可以通过类型检查。类似 `i == 1` 这样的比较,请参考[基本操作符](./05_Control_Flow.html)。 `i == 1` 的比较结果是 `Bool` 类型,所以第二个例子可以通过类型检查。类似 `i == 1` 这样的比较,请参考[基本操作符](./05_Control_Flow.md)。
和 Swift 中的其他类型安全的例子一样,这个方法可以避免错误并保证这块代码的意图总是清晰的。 和 Swift 中的其他类型安全的例子一样,这个方法可以避免错误并保证这块代码的意图总是清晰的。
@ -498,11 +498,11 @@ 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.md#Function_Parameters_and_Return_Values)。
> 注意 > 注意
> >
> 元组在临时组织值的时候很有用,但是并不适合创建复杂的数据结构。如果你的数据结构并不是临时使用,请使用类或者结构体而不是元组。请参考[类和结构体](./09_Classes_and_Structures.html)。 > 元组在临时组织值的时候很有用,但是并不适合创建复杂的数据结构。如果你的数据结构并不是临时使用,请使用类或者结构体而不是元组。请参考[类和结构体](./09_Classes_and_Structures.md)。
<a name="optionals"></a> <a name="optionals"></a>
## 可选类型 ## 可选类型
@ -576,7 +576,7 @@ if convertedNumber != nil {
// 输出“convertedNumber has an integer value of 123.” // 输出“convertedNumber has an integer value of 123.”
``` ```
更多关于 `if` 语句的内容,请参考[控制流](./05_Control_Flow.html)。 更多关于 `if` 语句的内容,请参考[控制流](./05_Control_Flow.md)。
> 注意 > 注意
> >
@ -585,7 +585,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.md)。
像下面这样在 `if` 语句中写一个可选绑定: 像下面这样在 `if` 语句中写一个可选绑定:
@ -595,7 +595,7 @@ if let constantName = someOptional {
} }
``` ```
你可以像上面这样使用可选绑定来重写 在[可选类型](./01_The_Basics.html#optionals)举出的 `possibleNumber` 例子: 你可以像上面这样使用可选绑定来重写 在[可选类型](./01_The_Basics.md#optionals)举出的 `possibleNumber` 例子:
```swift ```swift
if let actualNumber = Int(possibleNumber) { if let actualNumber = Int(possibleNumber) {
@ -634,7 +634,7 @@ if let firstNumber = Int("4") {
> 注意 > 注意
> >
> 在 `if` 条件语句中使用常量和变量来创建一个可选绑定,仅在 `if` 语句的句中(`body`)中才能获取到值。相反,在 `guard` 语句中使用常量和变量来创建一个可选绑定,仅在 `guard` 语句外且在语句后才能获取到值,请参考[提前退出](./05_Control_Flow.html#early_exit)。 > 在 `if` 条件语句中使用常量和变量来创建一个可选绑定,仅在 `if` 语句的句中(`body`)中才能获取到值。相反,在 `guard` 语句中使用常量和变量来创建一个可选绑定,仅在 `guard` 语句外且在语句后才能获取到值,请参考[提前退出](./05_Control_Flow.md#early_exit)。
<a name="implicityly_unwrapped_optionals"></a> <a name="implicityly_unwrapped_optionals"></a>
### 隐式解析可选类型 ### 隐式解析可选类型
@ -645,7 +645,7 @@ if let firstNumber = Int("4") {
这种类型的可选状态被定义为隐式解析可选类型implicitly unwrapped optionals。把想要用作可选的类型的后面的问号`String?`)改成感叹号(`String!`)来声明一个隐式解析可选类型。 这种类型的可选状态被定义为隐式解析可选类型implicitly unwrapped optionals。把想要用作可选的类型的后面的问号`String?`)改成感叹号(`String!`)来声明一个隐式解析可选类型。
当可选类型被第一次赋值之后就可以确定之后一直有值的时候,隐式解析可选类型非常有用。隐式解析可选类型主要被用在 Swift 中类的构造过程中,请参考[无主引用以及隐式解析可选属性](./23_Automatic_Reference_Counting.html#unowned_references_and_implicitly_unwrapped_optional_properties)。 当可选类型被第一次赋值之后就可以确定之后一直有值的时候,隐式解析可选类型非常有用。隐式解析可选类型主要被用在 Swift 中类的构造过程中,请参考[无主引用以及隐式解析可选属性](./23_Automatic_Reference_Counting.md#unowned_references_and_implicitly_unwrapped_optional_properties)。
一个隐式解析可选类型其实就是一个普通的可选类型,但是可以被当做非可选类型来使用,并不需要每次都使用解析来获取可选值。下面的例子展示了可选类型 `String` 和隐式解析可选类型 `String` 之间的区别: 一个隐式解析可选类型其实就是一个普通的可选类型,但是可以被当做非可选类型来使用,并不需要每次都使用解析来获取可选值。下面的例子展示了可选类型 `String` 和隐式解析可选类型 `String` 之间的区别:
@ -734,7 +734,7 @@ do {
如果没有错误被抛出,`eatASandwich()` 函数会被调用。如果一个匹配 `SandwichError.outOfCleanDishes` 的错误被抛出,`washDishes()` 函数会被调用。如果一个匹配 `SandwichError.missingIngredients` 的错误被抛出,`buyGroceries(_:)` 函数会被调用,并且使用 `catch` 所捕捉到的关联值 `[String]` 作为参数。 如果没有错误被抛出,`eatASandwich()` 函数会被调用。如果一个匹配 `SandwichError.outOfCleanDishes` 的错误被抛出,`washDishes()` 函数会被调用。如果一个匹配 `SandwichError.missingIngredients` 的错误被抛出,`buyGroceries(_:)` 函数会被调用,并且使用 `catch` 所捕捉到的关联值 `[String]` 作为参数。
抛出,捕捉,以及传播错误会在[错误处理](./17_Error_Handling.html)章节详细说明。 抛出,捕捉,以及传播错误会在[错误处理](./17_Error_Handling.md)章节详细说明。
<a name="assertions_and_preconditions"></a> <a name="assertions_and_preconditions"></a>
## 断言和先决条件 ## 断言和先决条件
@ -743,7 +743,7 @@ do {
你使用断言和先决条件来表达你所做的假设和你在编码时候的期望。你可以将这些包含在你的代码中。断言帮助你在开发阶段找到错误和不正确的假设,先决条件帮助你在生产环境中探测到存在的问题。 你使用断言和先决条件来表达你所做的假设和你在编码时候的期望。你可以将这些包含在你的代码中。断言帮助你在开发阶段找到错误和不正确的假设,先决条件帮助你在生产环境中探测到存在的问题。
除了在运行时验证你的期望值,断言和先决条件也变成了一个在你的代码中的有用的文档形式。和在上面讨论过的[错误处理](./17_Error_Handling.html)不同,断言和先决条件并不是用来处理可以恢复的或者可预期的错误。因为一个断言失败表明了程序正处于一个无效的状态,没有办法去捕获一个失败的断言。 除了在运行时验证你的期望值,断言和先决条件也变成了一个在你的代码中的有用的文档形式。和在上面讨论过的[错误处理](./17_Error_Handling.md)不同,断言和先决条件并不是用来处理可以恢复的或者可预期的错误。因为一个断言失败表明了程序正处于一个无效的状态,没有办法去捕获一个失败的断言。
使用断言和先决条件不是一个能够避免出现程序出现无效状态的编码方法。然而,如果一个无效状态程序产生了,断言和先决条件可以强制检查你的数据和程序状态,使得你的程序可预测的中止(译者:不是系统强制的,被动的中止),并帮助使这个问题更容易调试。一旦探测到无效的状态,执行则被中止,防止无效的状态导致的进一步对于系统的伤害。 使用断言和先决条件不是一个能够避免出现程序出现无效状态的编码方法。然而,如果一个无效状态程序产生了,断言和先决条件可以强制检查你的数据和程序状态,使得你的程序可预测的中止(译者:不是系统强制的,被动的中止),并帮助使这个问题更容易调试。一旦探测到无效的状态,执行则被中止,防止无效的状态导致的进一步对于系统的伤害。

View File

@ -2,11 +2,11 @@
*运算符*是检查、改变、合并值的特殊符号或短语。例如,加号(`+`)将两个数相加(如 `let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符 `&&`(如 `if enteredDoorCode && passedRetinaScan`)。 *运算符*是检查、改变、合并值的特殊符号或短语。例如,加号(`+`)将两个数相加(如 `let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符 `&&`(如 `if enteredDoorCode && passedRetinaScan`)。
Swift 支持大部分标准 C 语言的运算符,且为了减少常见编码错误做了部分改进。如:赋值符(`=`)不再有返回值,这样就消除了手误将判等运算符(`==`)写成赋值符导致代码错误的缺陷。算术运算符(`+``-``*``/``%` 等)的结果会被检测并禁止值溢出,以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果。当然允许你使用 Swift 的溢出运算符来实现溢出。详情参见[溢出运算符](./26_Advanced_Operators.html#overflow_operators)。 Swift 支持大部分标准 C 语言的运算符,且为了减少常见编码错误做了部分改进。如:赋值符(`=`)不再有返回值,这样就消除了手误将判等运算符(`==`)写成赋值符导致代码错误的缺陷。算术运算符(`+``-``*``/``%` 等)的结果会被检测并禁止值溢出,以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果。当然允许你使用 Swift 的溢出运算符来实现溢出。详情参见[溢出运算符](./26_Advanced_Operators.md#overflow_operators)。
Swift 还提供了 C 语言没有的区间运算符,例如 `a..<b``a...b`,这方便我们表达一个区间内的数值。 Swift 还提供了 C 语言没有的区间运算符,例如 `a..<b``a...b`,这方便我们表达一个区间内的数值。
本章节只描述了 Swift 中的基本运算符,[高级运算符](./26_Advanced_Operators.html)这章会包含 Swift 中的高级运算符,及如何自定义运算符,及如何进行自定义类型的运算符重载。 本章节只描述了 Swift 中的基本运算符,[高级运算符](./26_Advanced_Operators.md)这章会包含 Swift 中的高级运算符,及如何自定义运算符,及如何进行自定义类型的运算符重载。
<a name="terminology"></a> <a name="terminology"></a>
## 术语 ## 术语
@ -65,7 +65,7 @@ Swift 中所有数值类型都支持了基本的四则*算术运算符*
10.0 / 2.5 // 等于 4.0 10.0 / 2.5 // 等于 4.0
``` ```
与 C 语言和 Objective-C 不同的是Swift 默认情况下不允许在数值运算中出现溢出情况。但是你可以使用 Swift 的溢出运算符来实现溢出运算(如 `a &+ b`)。详情参见[溢出运算符](./26_Advanced_Operators.html#overflow_operators)。 与 C 语言和 Objective-C 不同的是Swift 默认情况下不允许在数值运算中出现溢出情况。但是你可以使用 Swift 的溢出运算符来实现溢出运算(如 `a &+ b`)。详情参见[溢出运算符](./26_Advanced_Operators.md#overflow_operators)。
加法运算符也可用于 `String` 的拼接: 加法运算符也可用于 `String` 的拼接:
@ -176,7 +176,7 @@ a += 2
> 注意 > 注意
> >
> Swift 也提供恒等(`===`)和不恒等(`!==`)这两个比较符来判断两个对象是否引用同一个对象实例。更多细节在[类与结构](./09_Classes_and_Structures.html)章节的 **Identity Operators** 部分。 > Swift 也提供恒等(`===`)和不恒等(`!==`)这两个比较符来判断两个对象是否引用同一个对象实例。更多细节在[类与结构](./09_Classes_and_Structures.md)章节的 **Identity Operators** 部分。
每个比较运算都返回了一个标识表达式是否成立的布尔值: 每个比较运算都返回了一个标识表达式是否成立的布尔值:
@ -201,7 +201,7 @@ if name == "world" {
// 输出“hello, world", 因为 `name` 就是等于 "world” // 输出“hello, world", 因为 `name` 就是等于 "world”
``` ```
关于 `if` 语句,请看[控制流](./05_Control_Flow.html)。 关于 `if` 语句,请看[控制流](./05_Control_Flow.md)。
如果两个元组的元素相同,且长度相同的话,元组就可以被比较。比较元组大小会按照从左到右、逐值比较的方式,直到发现有两个值不等时停止。如果所有的值都相等,那么这一对元组我们就称它们是相等的。例如: 如果两个元组的元素相同,且长度相同的话,元组就可以被比较。比较元组大小会按照从左到右、逐值比较的方式,直到发现有两个值不等时停止。如果所有的值都相等,那么这一对元组我们就称它们是相等的。例如:
@ -327,7 +327,7 @@ for index in 1...5 {
// 5 * 5 = 25 // 5 * 5 = 25
``` ```
关于 `for-in` 循环,请看[控制流](./05_Control_Flow.html)。 关于 `for-in` 循环,请看[控制流](./05_Control_Flow.md)。
<a name="half-open_range_operator"></a> <a name="half-open_range_operator"></a>
### 半开区间运算符 ### 半开区间运算符
@ -349,7 +349,7 @@ for i in 0..<count {
// 第 4 个人叫 Jack // 第 4 个人叫 Jack
``` ```
数组有 4 个元素,但 `0..<count` 只数到3最后一个元素的下标因为它是半开区间。关于数组请查阅[数组](./04_Collection_Types.html#arrays)。 数组有 4 个元素,但 `0..<count` 只数到3最后一个元素的下标因为它是半开区间。关于数组请查阅[数组](./04_Collection_Types.md#arrays)。
<a name="one-sided_ranges"></a> <a name="one-sided_ranges"></a>
### 单侧区间 ### 单侧区间

View File

@ -149,7 +149,7 @@ constantString += " and another Highlander"
<a name="strings_are_value_types"></a> <a name="strings_are_value_types"></a>
## 字符串是值类型 ## 字符串是值类型
在 Swift 中 `String` 类型是*值类型*。如果你创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。在前述任一情况下,都会对已有字符串值创建新副本,并对该新副本而非原始字符串进行传递或赋值操作。值类型在 [结构体和枚举是值类型](./09_Classes_and_Structures.html#structures_and_enumerations_are_value_types) 中进行了详细描述。 在 Swift 中 `String` 类型是*值类型*。如果你创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。在前述任一情况下,都会对已有字符串值创建新副本,并对该新副本而非原始字符串进行传递或赋值操作。值类型在 [结构体和枚举是值类型](./09_Classes_and_Structures.md#structures_and_enumerations_are_value_types) 中进行了详细描述。
Swift 默认拷贝字符串的行为保证了在函数/方法向你传递的字符串所属权属于你,无论该值来自于哪里。你可以确信传递的字符串不会被修改,除非你自己去修改它。 Swift 默认拷贝字符串的行为保证了在函数/方法向你传递的字符串所属权属于你,无论该值来自于哪里。你可以确信传递的字符串不会被修改,除非你自己去修改它。
@ -171,7 +171,7 @@ for character in "Dog!🐶" {
// 🐶 // 🐶
``` ```
`for-in` 循环在 [For 循环](./05_Control_Flow.html#for_loops) 中进行了详细描述。 `for-in` 循环在 [For 循环](./05_Control_Flow.md#for_loops) 中进行了详细描述。
另外,通过标明一个 `Character` 类型并用字符字面量进行赋值,可以建立一个独立的字符常量或变量: 另外,通过标明一个 `Character` 类型并用字符字面量进行赋值,可以建立一个独立的字符常量或变量:
@ -463,7 +463,7 @@ Swift 提供了三种方式来比较文本值:字符串字符相等、前缀
<a name="string_and_character_equality"></a> <a name="string_and_character_equality"></a>
### 字符串/字符相等 ### 字符串/字符相等
字符串/字符可以用等于操作符(`==`)和不等于操作符(`!=`),详细描述在[比较运算符](./02_Basic_Operators.html#comparison_operators) 字符串/字符可以用等于操作符(`==`)和不等于操作符(`!=`),详细描述在[比较运算符](./02_Basic_Operators.md#comparison_operators)
```swift ```swift
let quotation = "We're a lot alike, you and I." let quotation = "We're a lot alike, you and I."

View File

@ -8,7 +8,7 @@ Swift 语言中的 `Arrays`、`Sets` 和 `Dictionaries` 中存储的数据值类
> 注意 > 注意
> >
> Swift 的 `Arrays`、`Sets` 和 `Dictionaries` 类型被实现为*泛型集合*。更多关于泛型类型和集合,参见 [泛型](./23_Generics.html)章节。 > Swift 的 `Arrays`、`Sets` 和 `Dictionaries` 类型被实现为*泛型集合*。更多关于泛型类型和集合,参见 [泛型](./23_Generics.md)章节。
<a name="mutability_of_collections"></a> <a name="mutability_of_collections"></a>
## 集合的可变性 ## 集合的可变性
@ -261,7 +261,7 @@ for (index, value) in shoppingList.enumerated() {
一个类型为了存储在集合中,该类型必须是*可哈希化*的——也就是说,该类型必须提供一个方法来计算它的*哈希值*。一个哈希值是 `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.md)有讲述)默认也是可哈希化的。
> 注意 > 注意
> >
@ -273,7 +273,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.md)。
<a name="set_type_syntax"></a> <a name="set_type_syntax"></a>
### 集合类型语法 ### 集合类型语法
@ -396,7 +396,7 @@ for genre in favoriteGenres {
// Hip hop // Hip hop
``` ```
更多关于 `for-in` 循环的信息,参见[For 循环](./05_Control_Flow.html#for_loops)。 更多关于 `for-in` 循环的信息,参见[For 循环](./05_Control_Flow.md#for_loops)。
Swift 的 `Set` 类型没有确定的顺序,为了按照特定顺序来遍历一个 `Set` 中的值可以使用 `sorted()` 方法,它将返回一个有序数组,这个数组的元素排列顺序由操作符'<'对元素进行比较的结果来确定。 Swift 的 `Set` 类型没有确定的顺序,为了按照特定顺序来遍历一个 `Set` 中的值可以使用 `sorted()` 方法,它将返回一个有序数组,这个数组的元素排列顺序由操作符'<'对元素进行比较的结果来确定。
@ -640,7 +640,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.md#for_loops)。
通过访问 `keys` 或者 `values` 属性,我们也可以遍历字典的键或者值: 通过访问 `keys` 或者 `values` 属性,我们也可以遍历字典的键或者值:

View File

@ -36,7 +36,7 @@ for (animalName, legCount) in numberOfLegs {
// cats have 4 legs // cats have 4 legs
``` ```
字典的内容理论上是无序的,遍历元素时的顺序是无法确定的。将元素插入字典的顺序并不会决定它们被遍历的顺序。关于数组和字典的细节,参见[集合类型](./04_Collection_Types.html)。 字典的内容理论上是无序的,遍历元素时的顺序是无法确定的。将元素插入字典的顺序并不会决定它们被遍历的顺序。关于数组和字典的细节,参见[集合类型](./04_Collection_Types.md)。
`for-in` 循环还可以使用数字范围。下面的例子用来输出乘法表的一部分内容: `for-in` 循环还可以使用数字范围。下面的例子用来输出乘法表的一部分内容:
@ -70,7 +70,7 @@ print("\(base) to the power of \(power) is \(answer)")
这个例子计算 base 这个数的 power 次幂(本例中,是 `3``10` 次幂),从 `1``3``0` 次幂)开始做 `3` 的乘法, 进行 `10` 次,使用 `1``10` 的闭区间循环。这个计算并不需要知道每一次循环中计数器具体的值,只需要执行了正确的循环次数即可。下划线符号 `_` (替代循环中的变量)能够忽略当前值,并且不提供循环遍历时对值的访问。 这个例子计算 base 这个数的 power 次幂(本例中,是 `3``10` 次幂),从 `1``3``0` 次幂)开始做 `3` 的乘法, 进行 `10` 次,使用 `1``10` 的闭区间循环。这个计算并不需要知道每一次循环中计数器具体的值,只需要执行了正确的循环次数即可。下划线符号 `_` (替代循环中的变量)能够忽略当前值,并且不提供循环遍历时对值的访问。
在某些情况下,你可能不想使用包括两个端点的闭区间。想象一下,你在一个手表上绘制分钟的刻度线。总共 `60` 个刻度,从 `0` 分开始。使用半开区间运算符(`..<`)来表示一个左闭右开的区间。有关区间的更多信息,请参阅[区间运算符](./02_Basic_Operators.html#range_operators)。 在某些情况下,你可能不想使用包括两个端点的闭区间。想象一下,你在一个手表上绘制分钟的刻度线。总共 `60` 个刻度,从 `0` 分开始。使用半开区间运算符(`..<`)来表示一个左闭右开的区间。有关区间的更多信息,请参阅[区间运算符](./02_Basic_Operators.md#range_operators)。
```swift ```swift
let minutes = 60 let minutes = 60
@ -541,7 +541,7 @@ default:
- `return` - `return`
- `throw` - `throw`
我们将会在下面讨论 `continue``break``fallthrough` 语句。`return` 语句将会在[函数](./06_Functions.html)章节讨论,`throw` 语句会在[错误抛出](./18_Error_Handling.html#throwing_errors)章节讨论。 我们将会在下面讨论 `continue``break``fallthrough` 语句。`return` 语句将会在[函数](./06_Functions.md)章节讨论,`throw` 语句会在[错误抛出](./18_Error_Handling.md#throwing_errors)章节讨论。
<a name="continue"></a> <a name="continue"></a>
### Continue ### Continue

View File

@ -137,7 +137,7 @@ reversedNames = names.sorted(by: { $0 > $1 } )
reversedNames = names.sorted(by: >) reversedNames = names.sorted(by: >)
``` ```
更多关于运算符方法的内容请查看[运算符方法](./26_Advanced_Operators.html#operator_methods)。 更多关于运算符方法的内容请查看[运算符方法](./26_Advanced_Operators.md#operator_methods)。
<a name="trailing_closures"></a> <a name="trailing_closures"></a>
## 尾随闭包 ## 尾随闭包
@ -243,7 +243,7 @@ func makeIncrementer(forIncrement amount: Int) -> () -> Int {
} }
``` ```
`makeIncrementer` 返回类型为 `() -> Int`。这意味着其返回的是一个*函数*,而非一个简单类型的值。该函数在每次调用时不接受参数,只返回一个 `Int` 类型的值。关于函数返回其他函数的内容,请查看[函数类型作为返回类型](./06_Functions.html#function_types_as_return_types)。 `makeIncrementer` 返回类型为 `() -> Int`。这意味着其返回的是一个*函数*,而非一个简单类型的值。该函数在每次调用时不接受参数,只返回一个 `Int` 类型的值。关于函数返回其他函数的内容,请查看[函数类型作为返回类型](./06_Functions.md#function_types_as_return_types)。
`makeIncrementer(forIncrement:)` 函数定义了一个初始值为 `0` 的整型变量 `runningTotal`,用来存储当前总计数值。该值为 `incrementer` 的返回值。 `makeIncrementer(forIncrement:)` 函数定义了一个初始值为 `0` 的整型变量 `runningTotal`,用来存储当前总计数值。该值为 `incrementer` 的返回值。
@ -300,7 +300,7 @@ incrementByTen()
> 注意 > 注意
> >
> 如果你将闭包赋值给一个类实例的属性并且该闭包通过访问该实例或其成员而捕获了该实例你将在闭包和该实例间创建一个循环强引用。Swift 使用捕获列表来打破这种循环强引用。更多信息,请参考[闭包引起的循环强引用](./23_Automatic_Reference_Counting.html#strong_reference_cycles_for_closures)。 > 如果你将闭包赋值给一个类实例的属性并且该闭包通过访问该实例或其成员而捕获了该实例你将在闭包和该实例间创建一个循环强引用。Swift 使用捕获列表来打破这种循环强引用。更多信息,请参考[闭包引起的循环强引用](./23_Automatic_Reference_Counting.md#strong_reference_cycles_for_closures)。
<a name="closures_are_reference_types"></a> <a name="closures_are_reference_types"></a>
## 闭包是引用类型 ## 闭包是引用类型

View File

@ -8,7 +8,7 @@
在 Swift 中枚举类型是一等first-class类型。它们采用了很多在传统上只被类class所支持的特性例如计算属性computed properties用于提供枚举值的附加信息实例方法instance methods用于提供和枚举值相关联的功能。枚举也可以定义构造函数initializers来提供一个初始值可以在原始实现的基础上扩展它们的功能还可以遵循协议protocols来提供标准的功能。 在 Swift 中枚举类型是一等first-class类型。它们采用了很多在传统上只被类class所支持的特性例如计算属性computed properties用于提供枚举值的附加信息实例方法instance methods用于提供和枚举值相关联的功能。枚举也可以定义构造函数initializers来提供一个初始值可以在原始实现的基础上扩展它们的功能还可以遵循协议protocols来提供标准的功能。
想了解更多相关信息,请参见[属性](./10_Properties.html)[方法](./11_Methods.html)[构造过程](./14_Initialization.html)[扩展](./20_Extensions.html)和[协议](./21_Protocols.html)。 想了解更多相关信息,请参见[属性](./10_Properties.md)[方法](./11_Methods.md)[构造过程](./14_Initialization.md)[扩展](./20_Extensions.md)和[协议](./21_Protocols.md)。
<a name="enumeration_syntax"></a> <a name="enumeration_syntax"></a>
## 枚举语法 ## 枚举语法
@ -86,7 +86,7 @@ case .west:
……以此类推。 ……以此类推。
正如在[控制流](./05_Control_Flow.html)中介绍的那样,在判断一个枚举类型的值时,`switch` 语句必须穷举所有情况。如果忽略了 `.west` 这种情况,上面那段代码将无法通过编译,因为它没有考虑到 `CompassPoint` 的全部成员。强制穷举确保了枚举成员不会被意外遗漏。 正如在[控制流](./05_Control_Flow.md)中介绍的那样,在判断一个枚举类型的值时,`switch` 语句必须穷举所有情况。如果忽略了 `.west` 这种情况,上面那段代码将无法通过编译,因为它没有考虑到 `CompassPoint` 的全部成员。强制穷举确保了枚举成员不会被意外遗漏。
当不需要匹配每个枚举成员的时候,你可以提供一个 `default` 分支来涵盖所有未明确处理的枚举成员: 当不需要匹配每个枚举成员的时候,你可以提供一个 `default` 分支来涵盖所有未明确处理的枚举成员:
@ -128,7 +128,7 @@ for beverage in Beverage.allCases {
// juice // juice
``` ```
在前面的例子中,使用的语法表明这个枚举遵循 [CaseIterable](https://developer.apple.com/documentation/swift/caseiterable) 协议。想了解 protocols 相关信息,请参见[协议](./21_Protocols.html)。 在前面的例子中,使用的语法表明这个枚举遵循 [CaseIterable](https://developer.apple.com/documentation/swift/caseiterable) 协议。想了解 protocols 相关信息,请参见[协议](./21_Protocols.md)。
<a name="associated_values"></a> <a name="associated_values"></a>
## 关联值 ## 关联值
@ -217,7 +217,7 @@ enum ASCIIControlCharacter: Character {
} }
``` ```
枚举类型 `ASCIIControlCharacter` 的原始值类型被定义为 `Character`,并设置了一些比较常见的 ASCII 控制字符。`Character` 的描述详见[字符串和字符](./03_Strings_and_Characters.html)部分。 枚举类型 `ASCIIControlCharacter` 的原始值类型被定义为 `Character`,并设置了一些比较常见的 ASCII 控制字符。`Character` 的描述详见[字符串和字符](./03_Strings_and_Characters.md)部分。
原始值可以是字符串、字符,或者任意整型值或浮点型值。每个原始值在枚举声明中必须是唯一的。 原始值可以是字符串、字符,或者任意整型值或浮点型值。每个原始值在枚举声明中必须是唯一的。

View File

@ -20,7 +20,7 @@ Swift 中结构体和类有很多共同点。两者都可以:
* 通过扩展以增加默认实现之外的功能 * 通过扩展以增加默认实现之外的功能
* 遵循协议以提供某种标准功能 * 遵循协议以提供某种标准功能
更多信息请参见 [属性](./10_Properties.html)、[方法](./11_Methods.html)、[下标](./12_Subscripts.html)、[构造过程](./14_Initialization.html)、[扩展](./20_Extensions.html) 和 [协议](./21_Protocols.html)。 更多信息请参见 [属性](./{1}md{2})、[方法](./{1}md{2})、[下标](./{1}md{2})、[构造过程](./{1}md{2})、[扩展](./{1}md{2}) 和 [协议](./{1}md{2})。
与结构体相比,类还有如下的附加功能: 与结构体相比,类还有如下的附加功能:
@ -29,7 +29,7 @@ Swift 中结构体和类有很多共同点。两者都可以:
* 析构器允许一个类实例释放任何其所被分配的资源 * 析构器允许一个类实例释放任何其所被分配的资源
* 引用计数允许对一个类的多次引用 * 引用计数允许对一个类的多次引用
更多信息请参见 [继承](./13_Inheritance.html)、[类型转换](./18_Type_Casting.html)、[析构过程](./15_Deinitialization.html) 和 [自动引用计数](./23_Automatic_Reference_Counting.html)。 更多信息请参见 [继承](./{1}md{2})、[类型转换](./{1}md{2})、[析构过程](./{1}md{2}) 和 [自动引用计数](./{1}md{2})。
类支持的附加功能是以增加复杂性为代价的。作为一般准则,优先使用结构体,因为它们更容易理解,仅在适当或必要时才使用类。实际上,这意味着你的大多数自定义数据类型都会是结构体和枚举。更多详细的比较参见 [在结构和类之间进行选择](https://developer.apple.com/documentation/swift/choosing_between_structures_and_classes)。 类支持的附加功能是以增加复杂性为代价的。作为一般准则,优先使用结构体,因为它们更容易理解,仅在适当或必要时才使用类。实际上,这意味着你的大多数自定义数据类型都会是结构体和枚举。更多详细的比较参见 [在结构和类之间进行选择](https://developer.apple.com/documentation/swift/choosing_between_structures_and_classes)。
@ -82,7 +82,7 @@ let someResolution = Resolution()
let someVideoMode = VideoMode() let someVideoMode = VideoMode()
``` ```
结构体和类都使用构造器语法来创建新的实例。构造器语法的最简单形式是在结构体或者类的类型名称后跟随一对空括号,如 `Resolution()``VideoMode()`。通过这种方式所创建的类或者结构体实例,其属性均会被初始化为默认值。[构造过程](./14_Initialization.html) 章节会对类和结构体的初始化进行更详细的讨论。 结构体和类都使用构造器语法来创建新的实例。构造器语法的最简单形式是在结构体或者类的类型名称后跟随一对空括号,如 `Resolution()``VideoMode()`。通过这种方式所创建的类或者结构体实例,其属性均会被初始化为默认值。[构造过程](./{1}md{2}) 章节会对类和结构体的初始化进行更详细的讨论。
<a name="accessing_properties"></a> <a name="accessing_properties"></a>
### 属性访问 ### 属性访问
@ -120,7 +120,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) 章节会对构造器进行更详细的讨论。 与结构体不同,类实例没有默认的成员逐一构造器。[构造过程](./{1}md{2}) 章节会对构造器进行更详细的讨论。
<a name="structures_and_enumerations_are_value_types"></a> <a name="structures_and_enumerations_are_value_types"></a>
## 结构体和枚举是值类型 ## 结构体和枚举是值类型
@ -251,7 +251,7 @@ if tenEighty === alsoTenEighty {
请注意,“相同”(用三个等号表示,`===`)与“等于”(用两个等号表示,`==`的不同。“相同”表示两个类类型class type的常量或者变量引用同一个类实例。“等于”表示两个实例的值“相等”或“等价”判定时要遵照设计者定义的评判标准。 请注意,“相同”(用三个等号表示,`===`)与“等于”(用两个等号表示,`==`的不同。“相同”表示两个类类型class type的常量或者变量引用同一个类实例。“等于”表示两个实例的值“相等”或“等价”判定时要遵照设计者定义的评判标准。
当在定义你的自定义结构体和类的时候,你有义务来决定判定两个实例“相等”的标准。在章节 [等价操作符](./26_Advanced_Operators.html#equivalence_operators) 中将会详细介绍实现自定义 == 和 !== 运算符的流程。 当在定义你的自定义结构体和类的时候,你有义务来决定判定两个实例“相等”的标准。在章节 [等价操作符](./{1}md{2}) 中将会详细介绍实现自定义 == 和 !== 运算符的流程。
<a name="pointers"></a> <a name="pointers"></a>
### 指针 ### 指针

View File

@ -11,7 +11,7 @@
简单来说,一个存储属性就是存储在特定类或结构体实例里的一个常量或变量。存储属性可以是*变量存储属性*(用关键字 `var` 定义),也可以是*常量存储属性*(用关键字 `let` 定义)。 简单来说,一个存储属性就是存储在特定类或结构体实例里的一个常量或变量。存储属性可以是*变量存储属性*(用关键字 `var` 定义),也可以是*常量存储属性*(用关键字 `let` 定义)。
可以在定义存储属性的时候指定默认值,请参考[默认构造器](./14_Initialization.html#default_initializers)一节。也可以在构造过程中设置或修改存储属性的值,甚至修改常量存储属性的值,请参考[构造过程中常量属性的修改](./14_Initialization.html#assigning_constant_properties_during_initialization)一节。 可以在定义存储属性的时候指定默认值,请参考[默认构造器](./14_Initialization.md#default_initializers)一节。也可以在构造过程中设置或修改存储属性的值,甚至修改常量存储属性的值,请参考[构造过程中常量属性的修改](./14_Initialization.md#assigning_constant_properties_during_initialization)一节。
下面的例子定义了一个名为 `FixedLengthRange` 的结构体,该结构体用于描述整数的区间,且这个范围值在被创建后不能被修改。 下面的例子定义了一个名为 `FixedLengthRange` 的结构体,该结构体用于描述整数的区间,且这个范围值在被创建后不能被修改。
@ -210,7 +210,7 @@ print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
属性观察器监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,即使新值和当前值相同的时候也不例外。 属性观察器监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,即使新值和当前值相同的时候也不例外。
你可以为除了延时加载存储属性之外的其他存储属性添加属性观察器,你也可以在子类中通过重写属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。你不必为非重写的计算属性添加属性观察器,因为你可以直接通过它的 setter 监控和响应值的变化。属性重写请参考[重写](./13_Inheritance.html#overriding)。 你可以为除了延时加载存储属性之外的其他存储属性添加属性观察器,你也可以在子类中通过重写属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。你不必为非重写的计算属性添加属性观察器,因为你可以直接通过它的 setter 监控和响应值的变化。属性重写请参考[重写](./13_Inheritance.md#overriding)。
可以为属性添加其中一个或两个观察器: 可以为属性添加其中一个或两个观察器:
@ -225,7 +225,7 @@ print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
> >
> 在父类初始化方法调用之后,在子类构造器中给父类的属性赋值时,会调用父类属性的 `willSet` 和 `didSet` 观察器。而在父类初始化方法调用之前,给子类的属性赋值时不会调用子类属性的观察器。 > 在父类初始化方法调用之后,在子类构造器中给父类的属性赋值时,会调用父类属性的 `willSet` 和 `didSet` 观察器。而在父类初始化方法调用之前,给子类的属性赋值时不会调用子类属性的观察器。
> >
> 有关构造器代理的更多信息,请参考[值类型的构造器代理](./14_Initialization.html#initializer_delegation_for_value_types)和[类的构造器代理](./14_Initialization.html#initializer_delegation_for_class_types)。 > 有关构造器代理的更多信息,请参考[值类型的构造器代理](./14_Initialization.md#initializer_delegation_for_value_types)和[类的构造器代理](./14_Initialization.md#initializer_delegation_for_class_types)。
下面是一个 `willSet``didSet` 实际运用的例子,其中定义了一个名为 `StepCounter` 的类,用来统计一个人步行时的总步数。这个类可以跟计步器或其他日常锻炼的统计装置的输入数据配合使用。 下面是一个 `willSet``didSet` 实际运用的例子,其中定义了一个名为 `StepCounter` 的类,用来统计一个人步行时的总步数。这个类可以跟计步器或其他日常锻炼的统计装置的输入数据配合使用。

View File

@ -48,7 +48,7 @@ counter.reset()
// 计数值现在是0 // 计数值现在是0
``` ```
函数参数可以同时有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用),详情参见[指定外部参数名](./06_Functions.html#specifying_external_parameter_names)。方法参数也一样,因为方法就是函数,只是这个函数与某个类型相关联了。 函数参数可以同时有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用),详情参见[指定外部参数名](./06_Functions.md#specifying_external_parameter_names)。方法参数也一样,因为方法就是函数,只是这个函数与某个类型相关联了。
<a name="the_self_property"></a> <a name="the_self_property"></a>
### self 属性 ### self 属性
@ -110,7 +110,7 @@ print("The point is now at (\(somePoint.x), \(somePoint.y))")
上面的 `Point` 结构体定义了一个可变方法 `moveByxy :)` 来移动 `Point` 实例到给定的位置。该方法被调用时修改了这个点,而不是返回一个新的点。方法定义时加上了 `mutating` 关键字,从而允许修改属性。 上面的 `Point` 结构体定义了一个可变方法 `moveByxy :)` 来移动 `Point` 实例到给定的位置。该方法被调用时修改了这个点,而不是返回一个新的点。方法定义时加上了 `mutating` 关键字,从而允许修改属性。
注意不能在结构体类型的常量a constant of structure type上调用可变方法因为其属性不能被改变即使属性是变量属性详情参见[常量结构体的存储属性](./10_Properties.html#stored_properties_of_constant_structure_instances) 注意不能在结构体类型的常量a constant of structure type上调用可变方法因为其属性不能被改变即使属性是变量属性详情参见[常量结构体的存储属性](./10_Properties.md#stored_properties_of_constant_structure_instances)
```swift ```swift
let fixedPoint = Point(x: 3.0, y: 3.0) let fixedPoint = Point(x: 3.0, y: 3.0)

View File

@ -66,7 +66,7 @@ numberOfLegs["bird"] = 2
上例定义一个名为 `numberOfLegs` 的变量,并用一个包含三对键值的字典字面量初始化它。`numberOfLegs` 字典的类型被推断为 `[String: Int]`。字典创建完成后,该例子通过下标将 `String` 类型的键 `bird``Int` 类型的值 `2` 添加到字典中。 上例定义一个名为 `numberOfLegs` 的变量,并用一个包含三对键值的字典字面量初始化它。`numberOfLegs` 字典的类型被推断为 `[String: Int]`。字典创建完成后,该例子通过下标将 `String` 类型的键 `bird``Int` 类型的值 `2` 添加到字典中。
更多关于 `Dictionary` 下标的信息请参考 [读取和修改字典](./04_Collection_Types.html#accessing_and_modifying_a_dictionary)。 更多关于 `Dictionary` 下标的信息请参考 [读取和修改字典](./04_Collection_Types.md#accessing_and_modifying_a_dictionary)。
> 注意 > 注意
> >
@ -106,7 +106,7 @@ struct Matrix {
} }
``` ```
`Matrix` 提供了一个接受两个入参的构造方法,入参分别是 `rows``columns`,创建了一个足够容纳 `rows * columns``Double` 类型的值的数组。通过传入数组长度和初始值 `0.0` 到数组的构造器,将矩阵中每个位置的值初始化为 `0.0`。关于数组的这种构造方法请参考 [创建一个带有默认值的数组](./04_Collection_Types.html#creating_an_array_with_a_default_value)。 `Matrix` 提供了一个接受两个入参的构造方法,入参分别是 `rows``columns`,创建了一个足够容纳 `rows * columns``Double` 类型的值的数组。通过传入数组长度和初始值 `0.0` 到数组的构造器,将矩阵中每个位置的值初始化为 `0.0`。关于数组的这种构造方法请参考 [创建一个带有默认值的数组](./04_Collection_Types.md#creating_an_array_with_a_default_value)。
你可以通过传入合适的 `row``column` 的数量来构造一个新的 `Matrix` 实例: 你可以通过传入合适的 `row``column` 的数量来构造一个新的 `Matrix` 实例:

View File

@ -4,7 +4,7 @@
你要通过定义*构造器*来实现构造过程,它就像用来创建特定类型新实例的特殊方法。与 Objective-C 中的构造器不同Swift 的构造器没有返回值。它们的主要任务是保证某种类型的新实例在第一次使用前完成正确的初始化。 你要通过定义*构造器*来实现构造过程,它就像用来创建特定类型新实例的特殊方法。与 Objective-C 中的构造器不同Swift 的构造器没有返回值。它们的主要任务是保证某种类型的新实例在第一次使用前完成正确的初始化。
类的实例也可以通过实现*析构器*来执行它释放之前自定义的清理工作。想了解更多关于析构器的内容,请参考[析构过程](./15_Deinitialization.html)。 类的实例也可以通过实现*析构器*来执行它释放之前自定义的清理工作。想了解更多关于析构器的内容,请参考[析构过程](./15_Deinitialization.md)。
<a name="setting_initial_values_for_stored_properties"></a> <a name="setting_initial_values_for_stored_properties"></a>
@ -259,7 +259,7 @@ let twoByTwo = Size(width: 2.0, height: 2.0)
构造器可以通过调用其它构造器来完成实例的部分构造过程。这一过程称为*构造器代理*,它能避免多个构造器间的代码重复。 构造器可以通过调用其它构造器来完成实例的部分构造过程。这一过程称为*构造器代理*,它能避免多个构造器间的代码重复。
构造器代理的实现规则和形式在值类型和类类型中有所不同。值类型(结构体和枚举类型)不支持继承,所以构造器代理的过程相对简单,因为它们只能代理给自己的其它构造器。类则不同,它可以继承自其它类(请参考[继承](./13_Inheritance.html))。这意味着类有责任保证其所有继承的存储型属性在构造时也能正确的初始化。这些责任将在后续章节[类的继承和构造过程](#class_inheritance_and_initialization)中介绍。 构造器代理的实现规则和形式在值类型和类类型中有所不同。值类型(结构体和枚举类型)不支持继承,所以构造器代理的过程相对简单,因为它们只能代理给自己的其它构造器。类则不同,它可以继承自其它类(请参考[继承](./13_Inheritance.md))。这意味着类有责任保证其所有继承的存储型属性在构造时也能正确的初始化。这些责任将在后续章节[类的继承和构造过程](#class_inheritance_and_initialization)中介绍。
对于值类型,你可以使用 `self.init` 在自定义的构造器中引用相同类型中的其它构造器。并且你只能在构造器内部调用 `self.init` 对于值类型,你可以使用 `self.init` 在自定义的构造器中引用相同类型中的其它构造器。并且你只能在构造器内部调用 `self.init`
@ -267,7 +267,7 @@ let twoByTwo = Size(width: 2.0, height: 2.0)
> 注意 > 注意
> >
> 假如你希望默认构造器、逐一成员构造器以及你自己的自定义构造器都能用来创建实例,可以将自定义的构造器写到扩展(`extension`)中,而不是写在值类型的原始定义中。想查看更多内容,请查看[扩展](./20_Extensions.html)章节。 > 假如你希望默认构造器、逐一成员构造器以及你自己的自定义构造器都能用来创建实例,可以将自定义的构造器写到扩展(`extension`)中,而不是写在值类型的原始定义中。想查看更多内容,请查看[扩展](./20_Extensions.md)章节。
下面例子定义一个自定义结构体 `Rect`,用来代表几何矩形。这个例子需要两个辅助的结构体 `Size``Point`,它们各自为其所有的属性提供了默认初始值 `0.0` 下面例子定义一个自定义结构体 `Rect`,用来代表几何矩形。这个例子需要两个辅助的结构体 `Size``Point`,它们各自为其所有的属性提供了默认初始值 `0.0`
@ -329,7 +329,7 @@ let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
> 注意 > 注意
> >
> 如果你想用另外一种不需要自己定义 `init()` 和 `init(origin:size:)` 的方式来实现这个例子,请参考[扩展](./21_Extensions.html)。 > 如果你想用另外一种不需要自己定义 `init()` 和 `init(origin:size:)` 的方式来实现这个例子,请参考[扩展](./21_Extensions.md)。
<a name="class_inheritance_and_initialization"></a> <a name="class_inheritance_and_initialization"></a>
## 类的继承和构造过程 ## 类的继承和构造过程

View File

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

View File

@ -216,7 +216,7 @@ func printNumberOfRooms() {
} }
``` ```
这个方法没有返回值。然而,没有返回值的方法具有隐式的返回类型 `Void`,如[无返回值函数](./06_Functions.html#functions_without_return_values)中所述。这意味着没有返回值的方法也会返回 `()`,或者说空的元组。 这个方法没有返回值。然而,没有返回值的方法具有隐式的返回类型 `Void`,如[无返回值函数](./06_Functions.md#functions_without_return_values)中所述。这意味着没有返回值的方法也会返回 `()`,或者说空的元组。
如果在可选值上通过可选链式调用来调用这个方法,该方法的返回类型会是 `Void?`,而不是 `Void`,因为通过可选链式调用得到的返回值都是可选的。这样我们就可以使用 `if` 语句来判断能否成功调用 `printNumberOfRooms()` 方法,即使方法本身没有定义返回值。通过判断返回值是否为 `nil` 可以判断调用是否成功: 如果在可选值上通过可选链式调用来调用这个方法,该方法的返回类型会是 `Void?`,而不是 `Void`,因为通过可选链式调用得到的返回值都是可选的。这样我们就可以使用 `if` 语句来判断能否成功调用 `printNumberOfRooms()` 方法,即使方法本身没有定义返回值。通过判断返回值是否为 `nil` 可以判断调用是否成功:

View File

@ -4,7 +4,7 @@
类型转换在 Swift 中使用 `is``as` 操作符实现。这两个操作符分别提供了一种简单达意的方式去检查值的类型或者转换它的类型。 类型转换在 Swift 中使用 `is``as` 操作符实现。这两个操作符分别提供了一种简单达意的方式去检查值的类型或者转换它的类型。
你也可以用它来检查一个类型是否遵循了某个协议,就像在[检验协议遵循](./21_Protocols.html#checking_for_protocol_conformance)部分讲述的一样。 你也可以用它来检查一个类型是否遵循了某个协议,就像在[检验协议遵循](./21_Protocols.md#checking_for_protocol_conformance)部分讲述的一样。
<a name="defining_a_class_hierarchy_for_type_casting"></a> <a name="defining_a_class_hierarchy_for_type_casting"></a>
## 为类型转换定义类层次 ## 为类型转换定义类层次

View File

@ -64,7 +64,7 @@ struct BlackjackCard {
`BlackjackCard` 结构体拥有两个属性——`rank``suit`。它也同样定义了一个计算型属性 `description``description` 属性用 `rank``suit` 中的内容来构建对扑克牌名字和数值的描述。该属性使用可选绑定来检查可选类型 `second` 是否有值,若有值,则在原有的描述中增加对 `second` 的描述。 `BlackjackCard` 结构体拥有两个属性——`rank``suit`。它也同样定义了一个计算型属性 `description``description` 属性用 `rank``suit` 中的内容来构建对扑克牌名字和数值的描述。该属性使用可选绑定来检查可选类型 `second` 是否有值,若有值,则在原有的描述中增加对 `second` 的描述。
因为 `BlackjackCard` 是一个没有自定义构造器的结构体,在[结构体的逐一成员构造器](./14_Initialization.html#memberwise_initializers_for_structure_types)中可知,结构体有默认的成员构造器,所以你可以用默认的构造器去初始化新常量 `theAceOfSpades` 因为 `BlackjackCard` 是一个没有自定义构造器的结构体,在[结构体的逐一成员构造器](./14_Initialization.md#memberwise_initializers_for_structure_types)中可知,结构体有默认的成员构造器,所以你可以用默认的构造器去初始化新常量 `theAceOfSpades`
```swift ```swift
let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades) let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)

View File

@ -148,7 +148,7 @@ print("And another one: \(generator.random())")
<a name="mutating_method_requirements"></a> <a name="mutating_method_requirements"></a>
## 异变方法要求 ## 异变方法要求
有时需要在方法中改变(或*异变*)方法所属的实例。例如,在值类型(即结构体和枚举)的实例方法中,将 `mutating` 关键字作为方法的前缀,写在 `func` 关键字之前,表示可以在该方法中修改它所属的实例以及实例的任意属性的值。这一过程在 [在实例方法中修改值类型](./11_Methods.html#modifying_value_types_from_within_instance_methods) 章节中有详细描述。 有时需要在方法中改变(或*异变*)方法所属的实例。例如,在值类型(即结构体和枚举)的实例方法中,将 `mutating` 关键字作为方法的前缀,写在 `func` 关键字之前,表示可以在该方法中修改它所属的实例以及实例的任意属性的值。这一过程在 [在实例方法中修改值类型](./11_Methods.md#modifying_value_types_from_within_instance_methods) 章节中有详细描述。
如果你在协议中定义了一个实例方法,该方法会改变遵循该协议的类型的实例,那么在定义协议时需要在方法前加 `mutating` 关键字。这使得结构体和枚举能够遵循此协议并满足此方法要求。 如果你在协议中定义了一个实例方法,该方法会改变遵循该协议的类型的实例,那么在定义协议时需要在方法前加 `mutating` 关键字。这使得结构体和枚举能够遵循此协议并满足此方法要求。
@ -212,11 +212,11 @@ class SomeClass: SomeProtocol {
使用 `required` 修饰符可以确保所有子类也必须提供此构造器实现,从而也能符合协议。 使用 `required` 修饰符可以确保所有子类也必须提供此构造器实现,从而也能符合协议。
关于 `required` 构造器的更多内容,请参考 [必要构造器](./14_Initialization.html#required_initializers)。 关于 `required` 构造器的更多内容,请参考 [必要构造器](./14_Initialization.md#required_initializers)。
> 注意 > 注意
> >
> 如果类已经被标记为 `final`,那么不需要在协议构造器的实现中使用 `required` 修饰符,因为 `final` 类不能有子类。关于 `final` 修饰符的更多内容,请参见 [防止重写](./13_Inheritance.html#preventing_overrides)。 > 如果类已经被标记为 `final`,那么不需要在协议构造器的实现中使用 `required` 修饰符,因为 `final` 类不能有子类。关于 `final` 修饰符的更多内容,请参见 [防止重写](./13_Inheritance.md#preventing_overrides)。
如果一个子类重写了父类的指定构造器,并且该构造器满足了某个协议的要求,那么该构造器的实现需要同时标注 `required``override` 修饰符: 如果一个子类重写了父类的指定构造器,并且该构造器满足了某个协议的要求,那么该构造器的实现需要同时标注 `required``override` 修饰符:
@ -242,7 +242,7 @@ class SomeSubClass: SomeSuperClass, SomeProtocol {
### 可失败构造器要求 ### 可失败构造器要求
协议还可以为遵循协议的类型定义可失败构造器要求,详见 [可失败构造器](./14_Initialization.html#failable_initializers)。 协议还可以为遵循协议的类型定义可失败构造器要求,详见 [可失败构造器](./14_Initialization.md#failable_initializers)。
遵循协议的类型可以通过可失败构造器(`init?`)或非可失败构造器(`init`)来满足协议中定义的可失败构造器要求。协议中定义的非可失败构造器要求可以通过非可失败构造器(`init`)或隐式解包可失败构造器(`init!`)来满足。 遵循协议的类型可以通过可失败构造器(`init?`)或非可失败构造器(`init`)来满足协议中定义的可失败构造器要求。协议中定义的非可失败构造器要求可以通过非可失败构造器(`init`)或隐式解包可失败构造器(`init!`)来满足。
@ -320,9 +320,9 @@ protocol DiceGameDelegate {
`DiceGame` 协议可以被任意涉及骰子的游戏遵循。 `DiceGame` 协议可以被任意涉及骰子的游戏遵循。
`DiceGameDelegate` 协议可以被任意类型遵循,用来追踪 `DiceGame` 的游戏过程。为了防止强引用导致的循环引用问题,可以把协议声明为弱引用,更多相关的知识请看 [类实例之间的循环强引用](./23_Automatic_Reference_Counting.html#strong_reference_cycles_between_class_instances),当协议标记为类专属可以使 `SnakesAndLadders` 类在声明协议时强制要使用弱引用。若要声明类专属的协议就必须继承于 `AnyObject` ,更多请看 [类专属的协议](#class_only_protocol)。 `DiceGameDelegate` 协议可以被任意类型遵循,用来追踪 `DiceGame` 的游戏过程。为了防止强引用导致的循环引用问题,可以把协议声明为弱引用,更多相关的知识请看 [类实例之间的循环强引用](./23_Automatic_Reference_Counting.md#strong_reference_cycles_between_class_instances),当协议标记为类专属可以使 `SnakesAndLadders` 类在声明协议时强制要使用弱引用。若要声明类专属的协议就必须继承于 `AnyObject` ,更多请看 [类专属的协议](#class_only_protocol)。
如下所示,`SnakesAndLadders` 是 [控制流](./05_Control_Flow.html) 章节引入的蛇梯棋游戏的新版本。新版本使用 `Dice` 实例作为骰子,并且实现了 `DiceGame``DiceGameDelegate` 协议,后者用来记录游戏的过程: 如下所示,`SnakesAndLadders` 是 [控制流](./05_Control_Flow.md) 章节引入的蛇梯棋游戏的新版本。新版本使用 `Dice` 实例作为骰子,并且实现了 `DiceGame``DiceGameDelegate` 协议,后者用来记录游戏的过程:
```swift ```swift
class SnakesAndLadders: DiceGame { class SnakesAndLadders: DiceGame {
@ -357,7 +357,7 @@ class SnakesAndLadders: DiceGame {
} }
``` ```
关于这个*蛇梯棋*游戏的详细描述请参阅 [中断Break](./05_Control_Flow.html#break)。 关于这个*蛇梯棋*游戏的详细描述请参阅 [中断Break](./05_Control_Flow.md#break)。
这个版本的游戏封装到了 `SnakesAndLadders` 类中,该类遵循了 `DiceGame` 协议,并且提供了相应的可读的 `dice` 属性和 `play()` 方法。( `dice` 属性在构造之后就不再改变,且协议只要求 `dice` 为可读的,因此将 `dice` 声明为常量属性。) 这个版本的游戏封装到了 `SnakesAndLadders` 类中,该类遵循了 `DiceGame` 协议,并且提供了相应的可读的 `dice` 属性和 `play()` 方法。( `dice` 属性在构造之后就不再改变,且协议只要求 `dice` 为可读的,因此将 `dice` 声明为常量属性。)
@ -416,7 +416,7 @@ game.play()
<a name="adding_protocol_conformance_with_an_extension"></a> <a name="adding_protocol_conformance_with_an_extension"></a>
## 在扩展里添加协议遵循 ## 在扩展里添加协议遵循
即便无法修改源代码,依然可以通过扩展令已有类型遵循并符合协议。扩展可以为已有类型添加属性、方法、下标以及构造器,因此可以符合协议中的相应要求。详情请在 [扩展](./20_Extensions.html) 章节中查看。 即便无法修改源代码,依然可以通过扩展令已有类型遵循并符合协议。扩展可以为已有类型添加属性、方法、下标以及构造器,因此可以符合协议中的相应要求。详情请在 [扩展](./20_Extensions.md) 章节中查看。
> 注意 > 注意
> >
@ -465,7 +465,7 @@ print(game.textualDescription)
<a name="Conditionally_Conforming_to_a_Protocol"></a> <a name="Conditionally_Conforming_to_a_Protocol"></a>
## 有条件地遵循协议 ## 有条件地遵循协议
泛型类型可能只在某些情况下满足一个协议的要求,比如当类型的泛型形式参数遵循对应协议时。你可以通过在扩展类型时列出限制让泛型类型有条件地遵循某协议。在你采纳协议的名字后面写泛型 `where` 分句。更多关于泛型 `where` 分句,见 [泛型 Where 分句](./22_Generics.html##where_clauses)。 泛型类型可能只在某些情况下满足一个协议的要求,比如当类型的泛型形式参数遵循对应协议时。你可以通过在扩展类型时列出限制让泛型类型有条件地遵循某协议。在你采纳协议的名字后面写泛型 `where` 分句。更多关于泛型 `where` 分句,见 [泛型 Where 分句](./22_Generics.md##where_clauses)。
下面的扩展让 `Array` 类型只要在存储遵循 `TextRepresentable` 协议的元素时就遵循 `TextRepresentable` 协议。 下面的扩展让 `Array` 类型只要在存储遵循 `TextRepresentable` 协议的元素时就遵循 `TextRepresentable` 协议。
@ -512,7 +512,7 @@ print(somethingTextRepresentable.textualDescription)
<a name="collections_of_protocol_types"></a> <a name="collections_of_protocol_types"></a>
## 协议类型的集合 ## 协议类型的集合
协议类型可以在数组或者字典这样的集合中使用,在 [协议类型](./21_Protocols.html##protocols_as_types) 提到了这样的用法。下面的例子创建了一个元素类型为 `TextRepresentable` 的数组: 协议类型可以在数组或者字典这样的集合中使用,在 [协议类型](./21_Protocols.md##protocols_as_types) 提到了这样的用法。下面的例子创建了一个元素类型为 `TextRepresentable` 的数组:
```swift ```swift
let things: [TextRepresentable] = [game, d12, simonTheHamster] let things: [TextRepresentable] = [game, d12, simonTheHamster]
@ -603,7 +603,7 @@ protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
> 注意 > 注意
> >
> 当协议定义的要求需要遵循协议的类型必须是引用语义而非值语义时,应该采用类类型专属协议。关于引用语义和值语义的更多内容,请查看 [结构体和枚举是值类型](./09_Classes_and_Structures.html#structures_and_enumerations_are_value_types) 和 [类是引用类型](./09_Classes_and_Structures.html#classes_are_reference_types)。 > 当协议定义的要求需要遵循协议的类型必须是引用语义而非值语义时,应该采用类类型专属协议。关于引用语义和值语义的更多内容,请查看 [结构体和枚举是值类型](./09_Classes_and_Structures.md#structures_and_enumerations_are_value_types) 和 [类是引用类型](./09_Classes_and_Structures.md#classes_are_reference_types)。
<a name="protocol_composition"></a> <a name="protocol_composition"></a>
## 协议合成 ## 协议合成
@ -673,7 +673,7 @@ beginConcert(in: seattle)
<a name="checking_for_protocol_conformance"></a> <a name="checking_for_protocol_conformance"></a>
## 检查协议一致性 ## 检查协议一致性
你可以使用[类型转换](./18_Type_Casting.html)中描述的 `is``as` 操作符来检查协议一致性,即是否符合某协议,并且可以转换到指定的协议类型。检查和转换协议的语法与检查和转换类型是完全一样的: 你可以使用[类型转换](./18_Type_Casting.md)中描述的 `is``as` 操作符来检查协议一致性,即是否符合某协议,并且可以转换到指定的协议类型。检查和转换协议的语法与检查和转换类型是完全一样的:
* `is` 用来检查实例是否符合某个协议,若符合则返回 `true`,否则返回 `false` * `is` 用来检查实例是否符合某个协议,若符合则返回 `true`,否则返回 `false`
* `as?` 返回一个可选值,当实例符合某个协议时,返回类型为协议类型的可选值,否则返回 `nil` * `as?` 返回一个可选值,当实例符合某个协议时,返回类型为协议类型的可选值,否则返回 `nil`
@ -751,7 +751,7 @@ for object in objects {
使用可选要求时(例如,可选的方法或者属性),它们的类型会自动变成可选的。比如,一个类型为 `(Int) -> String` 的方法会变成 `((Int) -> String)?`。需要注意的是整个函数类型是可选的,而不是函数的返回值。 使用可选要求时(例如,可选的方法或者属性),它们的类型会自动变成可选的。比如,一个类型为 `(Int) -> String` 的方法会变成 `((Int) -> String)?`。需要注意的是整个函数类型是可选的,而不是函数的返回值。
协议中的可选要求可通过可选链式调用来使用,因为遵循协议的类型可能没有实现这些可选要求。类似 `someOptionalMethod?(someArgument)` 这样,你可以在可选方法名称后加上 `?` 来调用可选方法。详细内容可在[可选链式调用](./16_Optional_Chaining.html)章节中查看。 协议中的可选要求可通过可选链式调用来使用,因为遵循协议的类型可能没有实现这些可选要求。类似 `someOptionalMethod?(someArgument)` 这样,你可以在可选方法名称后加上 `?` 来调用可选方法。详细内容可在[可选链式调用](./16_Optional_Chaining.md)章节中查看。
下面的例子定义了一个名为 `Counter` 的用于整数计数的类,它使用外部的数据源来提供每次的增量。数据源由 `CounterDataSource` 协议定义,它包含两个可选要求: 下面的例子定义了一个名为 `Counter` 的用于整数计数的类,它使用外部的数据源来提供每次的增量。数据源由 `CounterDataSource` 协议定义,它包含两个可选要求:
@ -902,7 +902,7 @@ extension PrettyTextRepresentable {
<a name="adding_constraints_to_protocol_extensions"></a> <a name="adding_constraints_to_protocol_extensions"></a>
### 为协议扩展添加限制条件 ### 为协议扩展添加限制条件
在扩展协议的时候,可以指定一些限制条件,只有遵循协议的类型满足这些限制条件时,才能获得协议扩展提供的默认实现。这些限制条件写在协议名之后,使用 `where` 子句来描述,正如[泛型 Where 子句](./22_Generics.html#where_clauses)中所描述的。 在扩展协议的时候,可以指定一些限制条件,只有遵循协议的类型满足这些限制条件时,才能获得协议扩展提供的默认实现。这些限制条件写在协议名之后,使用 `where` 子句来描述,正如[泛型 Where 子句](./22_Generics.md#where_clauses)中所描述的。
例如,你可以扩展 `Collection` 协议,适用于集合中的元素遵循了 `Equatable` 协议的情况。通过限制集合元素遵 `Equatable` 协议, 作为标准库的一部分, 你可以使用 `==``!=` 操作符来检查两个元素的等价性和非等价性。 例如,你可以扩展 `Collection` 协议,适用于集合中的元素遵循了 `Equatable` 协议的情况。通过限制集合元素遵 `Equatable` 协议, 作为标准库的一部分, 你可以使用 `==``!=` 操作符来检查两个元素的等价性和非等价性。

View File

@ -17,7 +17,7 @@ func swapTwoInts(_ a: inout Int, _ b: inout Int) {
} }
``` ```
这个函数使用输入输出参数(`inout`)来交换 `a``b` 的值,具体请参考[输入输出参数](./06_Functions.html#in_out_parameters)。 这个函数使用输入输出参数(`inout`)来交换 `a``b` 的值,具体请参考[输入输出参数](./06_Functions.md#in_out_parameters)。
`swapTwoInts(_:_:)` 函数将 `b` 的原始值换成了 `a`,将 `a` 的原始值换成了 `b`,你可以调用这个函数来交换两个 `Int` 类型变量: `swapTwoInts(_:_:)` 函数将 `b` 的原始值换成了 `a`,将 `a` 的原始值换成了 `b`,你可以调用这个函数来交换两个 `Int` 类型变量:
@ -237,7 +237,7 @@ if let topItem = stackOfStrings.topItem {
`swapTwoValues(_:_:)` 函数和 `Stack` 适用于任意类型。不过,如果能对泛型函数或泛型类型中添加特定的*类型约束*,这将在某些情况下非常有用。类型约束指定类型参数必须继承自指定类、遵循特定的协议或协议组合。 `swapTwoValues(_:_:)` 函数和 `Stack` 适用于任意类型。不过,如果能对泛型函数或泛型类型中添加特定的*类型约束*,这将在某些情况下非常有用。类型约束指定类型参数必须继承自指定类、遵循特定的协议或协议组合。
例如Swift 的 `Dictionary` 类型对字典的键的类型做了些限制。在 [字典的描述](./04_Collection_Types.html#dictionaries) 中字典键的类型必须是可哈希hashable的。也就是说必须有一种方法能够唯一地表示它。字典键之所以要是可哈希的是为了便于检查字典中是否已经包含某个特定键的值。若没有这个要求字典将无法判断是否可以插入或替换某个指定键的值也不能查找到已经存储在字典中的指定键的值。 例如Swift 的 `Dictionary` 类型对字典的键的类型做了些限制。在 [字典的描述](./04_Collection_Types.md#dictionaries) 中字典键的类型必须是可哈希hashable的。也就是说必须有一种方法能够唯一地表示它。字典键之所以要是可哈希的是为了便于检查字典中是否已经包含某个特定键的值。若没有这个要求字典将无法判断是否可以插入或替换某个指定键的值也不能查找到已经存储在字典中的指定键的值。
这个要求通过 `Dictionary` 键类型上的类型约束实现,它指明了键必须遵循 Swift 标准库中定义的 `Hashable` 协议。所有 Swift 的基本类型(例如 `String``Int``Double``Bool`)默认都是可哈希的。 这个要求通过 `Dictionary` 键类型上的类型约束实现,它指明了键必须遵循 Swift 标准库中定义的 `Hashable` 协议。所有 Swift 的基本类型(例如 `String``Int``Double``Bool`)默认都是可哈希的。
@ -420,7 +420,7 @@ struct Stack<Element>: Container {
<a name="extending_an_existing_type_to_specify_an_associated_type"></a> <a name="extending_an_existing_type_to_specify_an_associated_type"></a>
### 扩展现有类型来指定关联类型 ### 扩展现有类型来指定关联类型
[在扩展添加协议一致性](./21_Protocols.html#adding_protocol_conformance_with_an_extension)中描述了如何利用扩展让一个已存在的类型符合一个协议,这包括使用了关联类型协议。 [在扩展添加协议一致性](./21_Protocols.md#adding_protocol_conformance_with_an_extension)中描述了如何利用扩展让一个已存在的类型符合一个协议,这包括使用了关联类型协议。
Swift 的 `Array` 类型已经提供 `append(_:)` 方法,`count` 属性,以及带有 `Int` 索引的下标来检索其元素。这三个功能都符合 `Container` 协议的要求,也就意味着你只需声明 `Array` 遵循`Container` 协议,就可以扩展 Array使其遵从 Container 协议。你可以通过一个空扩展来实现这点,正如通过扩展采纳协议中的描述: Swift 的 `Array` 类型已经提供 `append(_:)` 方法,`count` 属性,以及带有 `Int` 索引的下标来检索其元素。这三个功能都符合 `Container` 协议的要求,也就意味着你只需声明 `Array` 遵循`Container` 协议,就可以扩展 Array使其遵从 Container 协议。你可以通过一个空扩展来实现这点,正如通过扩展采纳协议中的描述:
@ -460,7 +460,7 @@ protocol SuffixableContainer: Container {
在这个协议里,`Suffix` 是一个关联类型,就像上边例子中 `Container``Item` 类型一样。`Suffix` 拥有两个约束:它必须遵循 `SuffixableContainer` 协议(就是当前定义的协议),以及它的 `Item` 类型必须是和容器里的 `Item` 类型相同。`Item` 的约束是一个 `where` 分句,它在下面带有泛型 `Where` 分句的扩展中有讨论。 在这个协议里,`Suffix` 是一个关联类型,就像上边例子中 `Container``Item` 类型一样。`Suffix` 拥有两个约束:它必须遵循 `SuffixableContainer` 协议(就是当前定义的协议),以及它的 `Item` 类型必须是和容器里的 `Item` 类型相同。`Item` 的约束是一个 `where` 分句,它在下面带有泛型 `Where` 分句的扩展中有讨论。
这是上面 [强引用循环闭包](./23_Automatic_Reference_Counting.html#strong_reference_cycles_for_closures) 中 `Stack` 类型的扩展,它遵循了 SuffixableContainer 协议: 这是上面 [强引用循环闭包](./23_Automatic_Reference_Counting.md#strong_reference_cycles_for_closures) 中 `Stack` 类型的扩展,它遵循了 SuffixableContainer 协议:
```swift ```swift
extension Stack: SuffixableContainer { extension Stack: SuffixableContainer {

View File

@ -366,9 +366,9 @@ class City {
为了建立两个类的依赖关系,`City` 的构造器接受一个 `Country` 实例作为参数,并且将实例保存到 `country` 属性。 为了建立两个类的依赖关系,`City` 的构造器接受一个 `Country` 实例作为参数,并且将实例保存到 `country` 属性。
`Country` 的构造器调用了 `City` 的构造器。然而,只有 `Country` 的实例完全初始化后,`Country` 的构造器才能把 `self` 传给 `City` 的构造器。在[两段式构造过程](./14_Initialization.html#two_phase_initialization)中有具体描述。 `Country` 的构造器调用了 `City` 的构造器。然而,只有 `Country` 的实例完全初始化后,`Country` 的构造器才能把 `self` 传给 `City` 的构造器。在[两段式构造过程](./14_Initialization.md#two_phase_initialization)中有具体描述。
为了满足这种需求,通过在类型结尾处加上感叹号(`City!`)的方式,将 `Country``capitalCity` 属性声明为隐式解包可选值类型的属性。这意味着像其他可选类型一样,`capitalCity` 属性的默认值为 `nil`,但是不需要展开它的值就能访问它。在[隐式解包可选值](./01_The_Basics.html#implicityly_unwrapped_optionals)中有描述。 为了满足这种需求,通过在类型结尾处加上感叹号(`City!`)的方式,将 `Country``capitalCity` 属性声明为隐式解包可选值类型的属性。这意味着像其他可选类型一样,`capitalCity` 属性的默认值为 `nil`,但是不需要展开它的值就能访问它。在[隐式解包可选值](./01_The_Basics.md#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` 的构造器。
@ -463,7 +463,7 @@ print(paragraph!.asHTML())
![](https://docs.swift.org/swift-book/_images/closureReferenceCycle01_2x.png) ![](https://docs.swift.org/swift-book/_images/closureReferenceCycle01_2x.png)
实例的 `asHTML` 属性持有闭包的强引用。但是,闭包在其闭包体内使用了 `self`(引用了 `self.name``self.text`),因此闭包捕获了 `self`,这意味着闭包又反过来持有了 `HTMLElement` 实例的强引用。这样两个对象就产生了循环强引用。(更多关于闭包捕获值的信息,请参考[值捕获](./07_Closures.html#capturing_values))。 实例的 `asHTML` 属性持有闭包的强引用。但是,闭包在其闭包体内使用了 `self`(引用了 `self.name``self.text`),因此闭包捕获了 `self`,这意味着闭包又反过来持有了 `HTMLElement` 实例的强引用。这样两个对象就产生了循环强引用。(更多关于闭包捕获值的信息,请参考[值捕获](./07_Closures.md#capturing_values))。
> 注意 > 注意
> >

View File

@ -300,14 +300,14 @@ public struct TrackedString {
<a name="initializers"></a> <a name="initializers"></a>
## 构造器 ## 构造器
自定义构造器的访问级别可以低于或等于其所属类型的访问级别。唯一的例外是[必要构造器](./14_Initialization.html#required_initializers),它的访问级别必须和所属类型的访问级别相同。 自定义构造器的访问级别可以低于或等于其所属类型的访问级别。唯一的例外是[必要构造器](./14_Initialization.md#required_initializers),它的访问级别必须和所属类型的访问级别相同。
如同函数或方法的参数,构造器参数的访问级别也不能低于构造器本身的访问级别。 如同函数或方法的参数,构造器参数的访问级别也不能低于构造器本身的访问级别。
<a name="default_initializers"></a> <a name="default_initializers"></a>
### 默认构造器 ### 默认构造器
如[默认构造器](./14_Initialization.html#default_initializers)所述Swift 会为结构体和类提供一个默认的无参数的构造器,只要它们为所有存储型属性设置了默认初始值,并且未提供自定义的构造器。 如[默认构造器](./14_Initialization.md#default_initializers)所述Swift 会为结构体和类提供一个默认的无参数的构造器,只要它们为所有存储型属性设置了默认初始值,并且未提供自定义的构造器。
默认构造器的访问级别与所属类型的访问级别相同,除非类型的访问级别是 `public`。如果一个类型被指定为 `public` 级别,那么默认构造器的访问级别将为 `internal`。如果你希望一个 `public` 级别的类型也能在其他模块中使用这种无参数的默认构造器,你只能自己提供一个 `public` 访问级别的无参数构造器。 默认构造器的访问级别与所属类型的访问级别相同,除非类型的访问级别是 `public`。如果一个类型被指定为 `public` 级别,那么默认构造器的访问级别将为 `internal`。如果你希望一个 `public` 级别的类型也能在其他模块中使用这种无参数的默认构造器,你只能自己提供一个 `public` 访问级别的无参数构造器。

View File

@ -300,7 +300,7 @@ let textB = "Hello world"
> <a id="interpolated-text"></a> > <a id="interpolated-text"></a>
> *插值文本* → [*插值文本项*](#interpolated-text-item) [*插值文本*](#interpolated-text)<sub>可选</sub> > *插值文本* → [*插值文本项*](#interpolated-text-item) [*插值文本*](#interpolated-text)<sub>可选</sub>
> <a id="interpolated-text-item"></a> > <a id="interpolated-text-item"></a>
> *插值文本项* → **\\****(**[*表达式*](./04_Expressions.html)**)** | [*引用文本项*](#quoted-text-item) > *插值文本项* → **\\****(**[*表达式*](./04_Expressions.md)**)** | [*引用文本项*](#quoted-text-item)
<a id="escaped-character"></a> <a id="escaped-character"></a>
> *转义字符* → **\\****0** | **\\****\\** | **\t** | **\n** | **\r** | **\\"** | **\\'** > *转义字符* → **\\****0** | **\\****\\** | **\t** | **\n** | **\r** | **\\"** | **\\'**

View File

@ -383,7 +383,7 @@ myFunction { $0 + $1 }
使用闭包表达式时,可以不必将其存储在一个变量或常量中,例如作为函数调用的一部分来立即使用一个闭包。在上面的例子中,传入 `myFunction` 的闭包表达式就是这种立即使用类型的闭包。因此,一个闭包是否逃逸与其使用时的上下文相关。一个会被立即调用或者作为函数的非逃逸参数传递的闭包表达式是非逃逸的,否则,这个闭包表达式是逃逸的。 使用闭包表达式时,可以不必将其存储在一个变量或常量中,例如作为函数调用的一部分来立即使用一个闭包。在上面的例子中,传入 `myFunction` 的闭包表达式就是这种立即使用类型的闭包。因此,一个闭包是否逃逸与其使用时的上下文相关。一个会被立即调用或者作为函数的非逃逸参数传递的闭包表达式是非逃逸的,否则,这个闭包表达式是逃逸的。
关于逃逸闭包的内容,请参阅[逃逸闭包](./chapter2/07_Closures.html#escaping_closures) 关于逃逸闭包的内容,请参阅[逃逸闭包](./chapter2/07_Closures.md#escaping_closures)
<a name="capture-lists"></a> <a name="capture-lists"></a>