统一中文括号使用,更新目录 (#783)

* 更新 01_The_Basics 目录

* 右后 01_The_Basics.md 目录层级,只显示二级目录

* 中文语句中统一使用中文括号

* 更新目录
This commit is contained in:
BqLin
2018-05-07 19:22:47 +08:00
committed by 安正超
parent 08a76e561f
commit 4a8365d78c
21 changed files with 342 additions and 308 deletions

View File

@ -29,32 +29,34 @@
本页包含内容:
- [常量和变量](#constants_and_variables)
- [声明常量和变量](#declaring)
- [类型标注](#type_annotations)
- [常量和变量的命名](#naming)
- [输出常量和变量](#printing)
- [声明常量和变量](#declaring)
- [类型标注](#type_annotations)
- [常量和变量的命名](#naming)
- [输出常量和变量](#printing)
- [注释](#comments)
- [分号](#semicolons)
- [整数](#integers)
- [整数范围](#integer_bounds)
- [Int](#Int)
- [UInt](#UInt)
- [整数范围](#integer_bounds)
- [Int](#Int)
- [UInt](#UInt)
- [浮点数](#floating-point_numbers)
- [类型安全和类型推断](#type_safety_and_type_inference)
- [数值型字面量](#numeric_literals)
- [数值型类型转换](#numeric_type_conversion)
- [整数转换](#integer_conversion)
- [数整数和浮点数转换](#integer_and_floating_point_conversion)
- [整数转换](#integer_conversion)
- [数整数和浮点数转换](#integer_and_floating_point_conversion)
- [类型别名](#type_aliases)
- [布尔值](#booleans)
- [元组](#tuples)
- [可选](#optionals)
- [nil](#nil)
- [if 语句以及强制解析](#if)
- [可选绑定](#optional_binding)
- [隐式解析可选类型](#implicityly_unwrapped_optionals)
- [可选类型](#optionals)
- [nil](#nil)
- [if 语句以及强制解析](#if)
- [可选绑定](#optional_binding)
- [隐式解析可选类型](#implicityly_unwrapped_optionals)
- [错误处理](#error_handling)
- [断言和先决条件](#assertions_and_Preconditions)
- [断言和先决条件](#assertions_and_preconditions)
- [使用断言进行调试](#debugging_with_assertions)
- [强制执行先决条件](#enforcing_preconditions)
Swift 是一门开发 iOS, macOS, watchOS 和 tvOS 应用的新语言。然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 Swift 的很多内容都是你熟悉的。
@ -245,7 +247,7 @@ let minValue = UInt8.min // minValue 为 0是 UInt8 类型
let maxValue = UInt8.max // maxValue 为 255是 UInt8 类型
```
`min``max` 所传回值的类型,正是其所对的整数类型(如上例 UInt8, 所传回的类型是 UInt8),可用在表达式中相同类型值旁。
`min``max` 所传回值的类型,正是其所对的整数类型如上例 UInt8, 所传回的类型是 UInt8,可用在表达式中相同类型值旁。
<a name="Int"></a>
### Int
@ -689,7 +691,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.html#early_exit)。
<a name="implicityly_unwrapped_optionals"></a>
### 隐式解析可选类型
@ -791,7 +793,7 @@ do {
抛出,捕捉,以及传播错误会在[错误处理](./17_Error_Handling.html)章节详细说明。
<a name="assertions_and_Preconditions"></a>
<a name="assertions_and_preconditions"></a>
## 断言和先决条件
断言和先决条件是在运行时所做的检查。你可以用他们来检查在执行后续代码之前是否一个必要的条件已经被满足了。如果断言或者先决条件中的布尔条件评估的结果为 true则代码像往常一样继续执行。如果布尔条件评估结果为 false程序的当前状态是无效的则代码执行结束应用程序中止。
@ -804,6 +806,7 @@ do {
断言和先决条件的不同点是,他们什么时候进行状态检测:断言仅在调试环境运行,而先决条件则在调试环境和生产环境中运行。在生产环境中,断言的条件将不会进行评估。这个意味着你可以使用很多断言在你的开发阶段,但是这些断言在生产环境中不会产生任何影响。
<a name="debugging_with_assertions"></a>
### 使用断言进行调试
你可以调用 Swift 标准库的 `assert(_:_:file:line:)` 函数来写一个断言。向这个函数传入一个结果为 `true` 或者 `false` 的表达式以及一条信息,当表达式的结果为 `false` 的时候这条信息会被显示:
@ -834,6 +837,7 @@ if age > 10 {
}
```
<a name="enforcing_preconditions"></a>
### 强制执行先决条件
当一个条件可能为假,但是继续执行代码要求条件必须为真的时候,需要使用先决条件。例如使用先决条件来检查是否下标越界,或者来检查是否将一个正确的参数传给函数。

View File

@ -26,11 +26,17 @@
- [术语](#terminology)
- [赋值运算符](#assignment_operator)
- [算术运算符](#arithmetic_operators)
- [求余运算符](#remainder_operator)
- [一元负号运算符](#unary_minus_operator)
- [一元正号运算符](#unary_plus_operator)
- [组合赋值运算符](#compound_assignment_operators)
- [比较运算符](#comparison_operators)
- [三目运算符](#ternary_conditional_operator)
- [空合运算符](#nil_coalescing_operator)
- [区间运算符](#range_operators)
- [闭区间运算符](#closed_range_operator)
- [半开区间运算符](#half-open_range_operator)
- [单侧区间](#one-sided_ranges)
- [逻辑运算符](#logical_operators)
*运算符*是检查、改变、合并值的特殊符号或短语。例如,加号(`+`)将两个数相加(如 `let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符 `&&`(如 `if enteredDoorCode && passedRetinaScan`)。
@ -106,6 +112,7 @@ Swift 中所有数值类型都支持了基本的四则*算术运算符*
"hello, " + "world" // 等于 "hello, world"
```
<a name="remainder_operator"></a>
### 求余运算符
*求余运算符*`a % b`)是计算 `b` 的多少倍刚刚好可以容入 `a`,返回多出来的那部分(余数)。
@ -150,6 +157,7 @@ Swift 中所有数值类型都支持了基本的四则*算术运算符*
在对负数 `b` 求余时,`b` 的符号会被忽略。这意味着 `a % b``a % -b` 的结果是相同的。
<a name="unary_minus_operator"></a>
### 一元负号运算符
数值的正负号可以使用前缀 `-`(即*一元负号符*)来切换:
@ -162,6 +170,7 @@ let plusThree = -minusThree // plusThree 等于 3, 或 "负负3"
一元负号符(`-`)写在操作数之前,中间没有空格。
<a name="unary_plus_operator"></a>
### 一元正号运算符
*一元正号符*`+`)不做任何改变地返回操作数的值:
@ -339,6 +348,7 @@ colorNameToUse = userDefinedColorName ?? defaultColorName
Swift 提供了几种方便表达一个区间的值的*区间运算符*。
<a name="closed_range_operator"></a>
### 闭区间运算符
*闭区间运算符*`a...b`)定义一个包含从 `a``b`(包括 `a``b`)的所有值的区间。`a` 的值不能超过 `b`
@ -358,7 +368,7 @@ for index in 1...5 {
关于 `for-in` 循环,请看[控制流](./05_Control_Flow.html)。
<a name="half-open_range_operator"></a>
### 半开区间运算符
*半开区间运算符*`a..<b`)定义一个从 `a``b` 但不包括 `b` 的区间。
@ -380,6 +390,7 @@ for i in 0..<count {
数组有 4 个元素,但 `0..<count` 只数到3最后一个元素的下标因为它是半开区间。关于数组请查阅[数组](./04_Collection_Types.html#arrays)。
<a name="one-sided_ranges"></a>
### 单侧区间
闭区间操作符有另一个表达形式,可以表达往一侧无限延伸的区间 —— 例如,一个包含了数组从索引 2 到结尾的所有值的区间。在这些情况下,你可以省略掉区间操作符一侧的值。这种区间叫做单侧区间,因为操作符只有一侧有值。例如:

View File

@ -84,7 +84,7 @@ till you come to the end; then stop."
"""
```
一个多行字符串字面量包含了所有的在开启和关闭引号(`"""`)中的行。这个字符从开启引号(`"""`)之后的第一行开始,到关闭引号(`"""`)之前为止。这就意味着字符串开启引号之后(`"""`)或者结束引号(`"""`)之前都没有换行符号。(译者:下面两个字符串其实是一样的,虽然第二个使用了多行字符串的形式)
一个多行字符串字面量包含了所有的在开启和关闭引号(`"""`)中的行。这个字符从开启引号`"""`之后的第一行开始,到关闭引号`"""`之前为止。这就意味着字符串开启引号之后`"""`或者结束引号`"""`之前都没有换行符号。(译者:下面两个字符串其实是一样的,虽然第二个使用了多行字符串的形式)
```swift
let singleLineString = "These are the same."
@ -93,7 +93,7 @@ These are the same.
"""
```
如果你的代码中,多行字符串字面量包含换行符的话,则多行字符串字面量中也会包含换行符。如果你想换行,以便加强代码的可读性,但是你又不想在你的多行字符串字面量中出现换行符的话,你可以用在行尾写一个反斜杠(`\`)作为续行符。
如果你的代码中,多行字符串字面量包含换行符的话,则多行字符串字面量中也会包含换行符。如果你想换行,以便加强代码的可读性,但是你又不想在你的多行字符串字面量中出现换行符的话,你可以用在行尾写一个反斜杠`\`作为续行符。
```swift
let softWrappedQuotation = """
@ -116,11 +116,11 @@ It also ends with a line break.
"""
```
一个多行字符串字面量能够缩进来匹配周围的代码。关闭引号(`"""`)之前的空白字符串告诉 Swift 编译器其他各行多少空白字符串需要忽略。然而,如果你在某行的前面写的空白字符串超出了关闭引号(`"""`)之前的空白字符串,则超出部分将被包含在多行字符串字面量中。
一个多行字符串字面量能够缩进来匹配周围的代码。关闭引号`"""`之前的空白字符串告诉 Swift 编译器其他各行多少空白字符串需要忽略。然而,如果你在某行的前面写的空白字符串超出了关闭引号`"""`之前的空白字符串,则超出部分将被包含在多行字符串字面量中。
![](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Art/multilineStringWhitespace_2x.png)
在上面的例子中,尽管整个多行字符串字面量都是缩进的(源代码缩进),第一行和最后一行没有以空白字符串开始(实际的变量值)。中间一行的缩进用空白字符串(源代码缩进)比关闭引号(`"""`)之前的空白字符串多所以它的行首将有4个空格。
在上面的例子中,尽管整个多行字符串字面量都是缩进的(源代码缩进),第一行和最后一行没有以空白字符串开始(实际的变量值)。中间一行的缩进用空白字符串(源代码缩进)比关闭引号`"""`之前的空白字符串多所以它的行首将有4个空格。
<a name="special_characters_in_string_literals"></a>
### 字符串字面量的特殊字符
@ -183,12 +183,12 @@ variableString += " and carriage"
let constantString = "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>
## 字符串是值类型
@ -249,7 +249,7 @@ var welcome = string1 + string2
// welcome 现在等于 "hello there"
```
您也可以通过加法赋值运算符 (`+=`) 将一个字符串添加到一个已经存在字符串变量上:
您也可以通过加法赋值运算符`+=`将一个字符串添加到一个已经存在字符串变量上:
```swift
var instruction = "look over"
@ -314,12 +314,12 @@ let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
当创建字符串执行插值计算时此占位符会被替换为 `multiplier` 实际的值。
`multiplier` 的值也作为字符串中后面表达式的一部分。
该表达式计算 `Double(multiplier) * 2.5` 的值并将结果 (`7.5`) 插入到字符串中。
该表达式计算 `Double(multiplier) * 2.5` 的值并将结果`7.5`插入到字符串中。
在这个例子中,表达式写为 `\(Double(multiplier) * 2.5)` 并包含在字符串字面量中。
> 注意
>
> 插值字符串中写在括号中的表达式不能包含非转义反斜杠 (`\`),并且不能包含回车或换行符。不过,插值字符串可以包含其他字面量。
> 插值字符串中写在括号中的表达式不能包含非转义反斜杠`\`,并且不能包含回车或换行符。不过,插值字符串可以包含其他字面量。
<a name="unicode"></a>
## Unicode
@ -332,11 +332,11 @@ Swift 的 `String` 和 `Character` 类型是完全兼容 Unicode 标准的。
### 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`
@ -347,7 +347,7 @@ Unicode 标量是对应字符或者修饰符的唯一的21位数字例如 `U+
每一个 Swift 的 `Character` 类型代表一个*可扩展的字形群*。
一个可扩展的字形群是一个或多个可生成人类可读的字符 Unicode 标量的有序排列。
举个例子,字母 `é` 可以用单一的 Unicode 标量 `é`(`LATIN SMALL LETTER E WITH ACUTE`, 或者 `U+00E9`)来表示。然而一个标准的字母 `e`(`LATIN SMALL LETTER E` 或者 `U+0065`) 加上一个急促重音(`COMBINING ACTUE ACCENT`)的标量(`U+0301`),这样一对标量就表示了同样的字母 `é`
举个例子,字母 `é` 可以用单一的 Unicode 标量 `é`(`LATIN SMALL LETTER E WITH ACUTE`, 或者 `U+00E9`)来表示。然而一个标准的字母 `e`(`LATIN SMALL LETTER E` 或者 `U+0065`) 加上一个急促重音`COMBINING ACTUE ACCENT`的标量`U+0301`,这样一对标量就表示了同样的字母 `é`
这个急促重音的标量形象的将 `e` 转换成了 `é`
在这两种情况中,字母 `é` 代表了一个单一的 Swift 的 `Character` 值,同时代表了一个可扩展的字形群。
@ -369,7 +369,7 @@ let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
// precomposed 是 한, decomposed 是 한
```
可拓展的字符群集可以使包围记号(例如 `COMBINING ENCLOSING CIRCLE` 或者 `U+20DD`)的标量包围其他 Unicode 标量,作为一个单一的 `Character` 值:
可拓展的字符群集可以使包围记号例如 `COMBINING ENCLOSING CIRCLE` 或者 `U+20DD`的标量包围其他 Unicode 标量,作为一个单一的 `Character` 值:
```swift
let enclosedEAcute: Character = "\u{E9}\u{20DD}"
@ -423,9 +423,9 @@ print("the number of characters in \(word) is \(word.count)")
<a name="string_indices"></a>
### 字符串索引
每一个 `String` 值都有一个关联的索引(*index*)类型,`String.Index`,它对应着字符串中的每一个 `Character` 的位置。
每一个 `String` 值都有一个关联的索引*index*类型,`String.Index`,它对应着字符串中的每一个 `Character` 的位置。
前面提到,不同的字符可能会占用不同数量的内存空间,所以要知道 `Character` 的确定位置,就必须从 `String` 开头遍历每一个 Unicode 标量直到结尾。因此Swift 的字符串不能用整数(integer)做索引。
前面提到,不同的字符可能会占用不同数量的内存空间,所以要知道 `Character` 的确定位置,就必须从 `String` 开头遍历每一个 Unicode 标量直到结尾。因此Swift 的字符串不能用整数integer做索引。
使用 `startIndex` 属性可以获取一个 `String` 的第一个 `Character` 的索引。使用 `endIndex` 属性可以获取最后一个 `Character` 的后一个位置的索引。因此,`endIndex` 属性不能作为一个字符串的有效下标。如果 `String` 是空串,`startIndex``endIndex` 是相等的。
@ -453,7 +453,7 @@ greeting[greeting.endIndex] // error
greeting.index(after: endIndex) // error
```
使用 `indices` 属性会创建一个包含全部索引的范围(`Range`),用来在一个字符串中访问单个字符。
使用 `indices` 属性会创建一个包含全部索引的范围`Range`,用来在一个字符串中访问单个字符。
```swift
for index in greeting.indices {
@ -528,7 +528,7 @@ Swift 提供了三种方式来比较文本值:字符串字符相等、前缀
<a name="string_and_character_equality"></a>
### 字符串/字符相等
字符串/字符可以用等于操作符(`==`)和不等于操作符(`!=`),详细描述在[比较运算符](./02_Basic_Operators.html#comparison_operators)
字符串/字符可以用等于操作符`==`和不等于操作符`!=`,详细描述在[比较运算符](./02_Basic_Operators.html#comparison_operators)
```swift
let quotation = "We're a lot alike, you and I."
@ -571,7 +571,7 @@ if latinCapitalLetterA != cyrillicCapitalLetterA {
> 注意
>
> 在 Swift 中,字符串和字符并不区分地域(not locale-sensitive)
> 在 Swift 中,字符串和字符并不区分地域not locale-sensitive
<a name="prefix_and_suffix_equality"></a>
### 前缀/后缀相等
@ -640,9 +640,9 @@ Swift 提供了几种不同的方式来访问字符串的 Unicode 表示形式
另外,能够以其他三种 Unicode 兼容的方式访问字符串的值:
* UTF-8 代码单元集合 (利用字符串的 `utf8` 属性进行访问)
* UTF-16 代码单元集合 (利用字符串的 `utf16` 属性进行访问)
* 21位的 Unicode 标量值集合,也就是字符串的 UTF-32 编码格式 (利用字符串的 `unicodeScalars` 属性进行访问)
* UTF-8 代码单元集合利用字符串的 `utf8` 属性进行访问
* UTF-16 代码单元集合利用字符串的 `utf16` 属性进行访问
* 21位的 Unicode 标量值集合,也就是字符串的 UTF-32 编码格式利用字符串的 `unicodeScalars` 属性进行访问
下面由 `D`,`o`,`g`,`‼`(`DOUBLE EXCLAMATION MARK`, Unicode 标量 `U+203C`)和 `🐶`(`DOG FACE`Unicode 标量为 `U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示:
@ -654,7 +654,7 @@ let dogString = "Dog‼🐶"
### UTF-8 表示
您可以通过遍历 `String``utf8` 属性来访问它的 `UTF-8` 表示。
其为 `String.UTF8View` 类型的属性,`UTF8View` 是无符号8位 (`UInt8`) 值的集合,每一个 `UInt8` 值都是一个字符的 UTF-8 表示:
其为 `String.UTF8View` 类型的属性,`UTF8View` 是无符号8位`UInt8`值的集合,每一个 `UInt8` 值都是一个字符的 UTF-8 表示:
<table style='text-align:center'>
<tr height="77">
@ -701,15 +701,15 @@ print("")
// 68 111 103 226 128 188 240 159 144 182
```
上面的例子中前三个10进制 `codeUnit` (`68`, `111`, `103`) 代表了字符 `D``o``g`,它们的 UTF-8 表示与 ASCII 表示相同。
接下来的三个10进制 `codeUnit` (`226`, `128`, `188`) `DOUBLE EXCLAMATION MARK` 的3字节 UTF-8 表示。
最后的四个 `codeUnit` (`240`, `159`, `144`, `182`) `DOG FACE` 的4字节 UTF-8 表示。
上面的例子中前三个10进制 `codeUnit``68``111``103`代表了字符 `D``o``g`,它们的 UTF-8 表示与 ASCII 表示相同。
接下来的三个10进制 `codeUnit``226``128``188``DOUBLE EXCLAMATION MARK` 的3字节 UTF-8 表示。
最后的四个 `codeUnit``240``159``144``182``DOG FACE` 的4字节 UTF-8 表示。
<a name="UTF-16_representation"></a>
### UTF-16 表示
您可以通过遍历 `String``utf16` 属性来访问它的 `UTF-16` 表示。
其为 `String.UTF16View` 类型的属性,`UTF16View` 是无符号16位 (`UInt16`) 值的集合,每一个 `UInt16` 都是一个字符的 UTF-16 表示:
其为 `String.UTF16View` 类型的属性,`UTF16View` 是无符号16位`UInt16`值的集合,每一个 `UInt16` 都是一个字符的 UTF-16 表示:
<table style='text-align:center'>
<tr height="77">
@ -748,11 +748,11 @@ print("")
// 68 111 103 8252 55357 56374
```
同样,前三个 `codeUnit` (`68`, `111`, `103`) 代表了字符 `D``o``g`,它们的 UTF-16 代码单元和 UTF-8 完全相同(因为这些 Unicode 标量表示 ASCII 字符)。
同样,前三个 `codeUnit``68``111``103`代表了字符 `D``o``g`,它们的 UTF-16 代码单元和 UTF-8 完全相同(因为这些 Unicode 标量表示 ASCII 字符)。
第四个 `codeUnit` (`8252`) 是一个等于十六进制 `203C` 的的十进制值。这个代表了 `DOUBLE EXCLAMATION MARK` 字符的 Unicode 标量值 `U+203C`。这个字符在 UTF-16 中可以用一个代码单元表示。
第四个 `codeUnit``8252`是一个等于十六进制 `203C` 的的十进制值。这个代表了 `DOUBLE EXCLAMATION MARK` 字符的 Unicode 标量值 `U+203C`。这个字符在 UTF-16 中可以用一个代码单元表示。
第五和第六个 `codeUnit` (`55357``56374`) `DOG FACE` 字符的 UTF-16 表示。
第五和第六个 `codeUnit``55357``56374``DOG FACE` 字符的 UTF-16 表示。
第一个值为 `U+D83D`(十进制值为 `55357`),第二个值为 `U+DC36`(十进制值为 `56374`)。
<a name="unicode_scalars_representation"></a>
@ -799,9 +799,9 @@ print("")
// 68 111 103 8252 128054
```
前三个 `UnicodeScalar`(`68`, `111`, `103`)`value` 属性仍然代表字符 `D``o``g`
前三个 `UnicodeScalar``68``111``103``value` 属性仍然代表字符 `D``o``g`
第四个 `codeUnit`(`8252`)仍然是一个等于十六进制 `203C` 的十进制值。这个代表了 `DOUBLE EXCLAMATION MARK` 字符的 Unicode 标量 `U+203C`
第四个 `codeUnit``8252`仍然是一个等于十六进制 `203C` 的十进制值。这个代表了 `DOUBLE EXCLAMATION MARK` 字符的 Unicode 标量 `U+203C`
第五个 `UnicodeScalar` 值的 `value` 属性,`128054`,是一个十六进制 `1F436` 的十进制表示。其等同于 `DOG FACE` 的 Unicode 标量 `U+1F436`

View File

@ -1,4 +1,4 @@
# 集合类型 (Collection Types)
# 集合类型Collection Types
-----------------
> 1.0
@ -25,9 +25,28 @@
- [集合的可变性](#mutability_of_collections)
- [数组](#arrays)
- [创建一个空数组](#creating_an_empty_array)
- [创建一个带有默认值的数组](#creating_an_array_with_a_default_value)
- [通过两个数组相加创建一个数组](#creating_an_array_by_adding_two_arrays_together)
- [用数组字面量构造数组](#creating_an_array_with_an_array_literals)
- [访问和修改数组](#accessing_and_modifying_an_array)
- [数组的遍历](#iterating_over_an_array)
- [集合](#sets)
- [集合类型的哈希值](#hash_values_for_set_types)
- [集合类型语法](#set_type_syntax)
- [创建和构造一个空的集合](#creating_and_initalizing_an_empty_set)
- [用数组字面量创建集合](#creating_a_set_with_an_array_literal)
- [访问和修改一个集合](#accesing_and_modifying_a_set)
- [遍历一个集合](#iterating_over_a_set)
- [集合操作](#performing_set_operations)
- [基本集合操作](#fundamental_set_operations)
- [集合成员关系和相等](#set_membership_and_equality)
- [字典](#dictionaries)
- [字典类型简化语法](#dictionary_type_shorthand_syntax)
- [创建一个空字典](#creating_an_empty_dictionary)
- [用字典字面量创建字典](#creating_a_dictionary_with_a_dictionary_literal)
- [访问和修改字典](#accessing_and_modifying_a_dictionary)
- [字典遍历](#iterating_over_a_dictionary)
Swift 语言提供 `Arrays``Sets``Dictionaries` 三种基本的*集合类型*用来存储集合数据。数组Arrays是有序数据的集。集合Sets是无序无重复数据的集。字典Dictionaries是无序的键值对的集。
@ -49,7 +68,7 @@ Swift 语言中的 `Arrays`、`Sets` 和 `Dictionaries` 中存储的数据值类
> 在我们不需要改变集合的时候创建不可变集合是很好的实践。如此 Swift 编译器可以优化我们创建的集合。
<a name="arrays"></a>
## 数组(Arrays)
## 数组Arrays
*数组*使用有序列表存储同一类型的多个值。相同的值可以多次出现在一个数组的不同位置中。
@ -278,7 +297,7 @@ for (index, value) in shoppingList. enumerated() {
<a name="sets"></a>
## 集合Sets
*集合(Set)*用来存储相同类型并且没有确定顺序的值。当集合元素顺序不重要时或者希望确保每个元素只出现一次时可以使用集合而不是数组。
*集合Set*用来存储相同类型并且没有确定顺序的值。当集合元素顺序不重要时或者希望确保每个元素只出现一次时可以使用集合而不是数组。
> 注意
> Swift 的 `Set` 类型被桥接到 `Foundation` 中的 `NSSet` 类。
@ -286,17 +305,17 @@ for (index, value) in shoppingList. enumerated() {
> 关于使用 `Foundation` 和 `Cocoa` 中 `Set` 的知识,参见 [*Using Swift with Cocoa and Obejective-C(Swift 4.1)*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216) 中[使用 Cocoa 数据类型](https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6)部分。
<a name="hash_values_for_set_types"></a>
#### 集合类型的哈希值
### 集合类型的哈希值
一个类型为了存储在集合中,该类型必须是*可哈希化*的--也就是说,该类型必须提供一个方法来计算它的*哈希值*。一个哈希值是 `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` 属性返回的值不需要在同一程序的不同执行周期或者不同程序之间保持相同。
>
> 因为 `Hashable` 协议符合 `Equatable` 协议,所以遵循该协议的类型也必须提供一个“是否相等”运算符(`==`)的实现。这个 `Equatable` 协议要求任何符合 `==` 实现的实例间都是一种相等的关系。也就是说,对于 `a,b,c` 三个值来说,`==` 的实现必须满足下面三种情况:
> 因为 `Hashable` 协议符合 `Equatable` 协议,所以遵循该协议的类型也必须提供一个“是否相等”运算符`==`的实现。这个 `Equatable` 协议要求任何符合 `==` 实现的实例间都是一种相等的关系。也就是说,对于 `a,b,c` 三个值来说,`==` 的实现必须满足下面三种情况:
> * `a == a`(自反性)
> * `a == b` 意味着 `b == a`(对称性)
@ -345,11 +364,11 @@ var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres 被构造成含有三个初始值的集合
```
这个 `favoriteGenres` 变量被声明为“一个 `String` 值的集合”,写为 `Set<String>`。由于这个特定的集合含有指定 `String` 类型的值,所以它只允许存储 `String` 类型值。这里的 `favoriteGenres` 变量有三个 `String` 类型的初始值(`"Rock"``"Classical"``"Hip hop"`),并以数组字面量的方式出现。
这个 `favoriteGenres` 变量被声明为“一个 `String` 值的集合”,写为 `Set<String>`。由于这个特定的集合含有指定 `String` 类型的值,所以它只允许存储 `String` 类型值。这里的 `favoriteGenres` 变量有三个 `String` 类型的初始值`"Rock"``"Classical"``"Hip hop"`,并以数组字面量的方式出现。
> 注意
>
> `favoriteGenres` 被声明为一个变量(拥有 `var` 标示符)而不是一个常量(拥有 `let` 标示符),因为它里面的元素将会在下面的例子中被增加或者移除。
> `favoriteGenres` 被声明为一个变量拥有 `var` 标示符而不是一个常量拥有 `let` 标示符,因为它里面的元素将会在下面的例子中被增加或者移除。
一个 `Set` 类型不能从数组字面量中被单独推断出来,因此 `Set` 类型必须显式声明。然而,由于 Swift 的类型推断功能,如果你想使用一个数组字面量构造一个 `Set` 并且该数组字面量中的所有元素类型相同,那么你无须写出 `Set` 的具体类型。`favoriteGenres` 的构造形式可以采用简化的方式代替:
@ -477,11 +496,11 @@ oddDigits. symmetricDifference(singleDigitPrimeNumbers).sorted()
![](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/setEulerDiagram_2x.png)
* 使用“是否相等”运算符(`==`)来判断两个集合是否包含全部相同的值。
* 使用“是否相等”运算符`==`来判断两个集合是否包含全部相同的值。
* 使用 `isSubset(of:)` 方法来判断一个集合中的值是否也被包含在另外一个集合中。
* 使用 `isSuperset(of:)` 方法来判断一个集合中包含另一个集合中所有的值。
* 使用 `isStrictSubset(of:)` 或者 `isStrictSuperset(of:)` 方法来判断一个集合是否是另外一个集合的子集合或者父集合并且两个集合并不相等。
* 使用 `isDisjoint(with:)` 方法来判断两个集合是否不含有相同的值(是否没有交集)
* 使用 `isDisjoint(with:)` 方法来判断两个集合是否不含有相同的值是否没有交集
```swift
let houseAnimals: Set = ["🐶", "🐱"]
@ -540,7 +559,7 @@ namesOfIntegers = [:]
```
<a name="creating_a_dictionary_with_a_dictionary_literal"></a>
## 用字典字面量创建字典
### 用字典字面量创建字典
我们可以使用*字典字面量*来构造字典,这和我们刚才介绍过的数组字面量拥有相似语法。字典字面量是一种将一个或多个键值对写作 `Dictionary` 集合的快捷途径。

View File

@ -122,7 +122,7 @@ for tickMark in 0..<minutes {
```swift
let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
// 每5分钟渲染一个刻度线 (0, 5, 10, 15 ... 45, 50, 55)
// 每5分钟渲染一个刻度线0, 5, 10, 15 ... 45, 50, 55
}
```
@ -132,7 +132,7 @@ for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
// 每3小时渲染一个刻度线 (3, 6, 9, 12)
// 每3小时渲染一个刻度线3, 6, 9, 12
}
```
@ -350,7 +350,7 @@ default:
`switch` 语句由*多个 case* 构成,每个由 `case` 关键字开始。为了匹配某些更特定的值Swift 提供了几种方法来进行更复杂的模式匹配,这些模式将在本节的稍后部分提到。
`if` 语句类似,每一个 case 都是代码执行的一条分支。`switch` 语句会决定哪一条分支应该被执行,这个流程被称作根据给定的值*切换(switching)*。
`if` 语句类似,每一个 case 都是代码执行的一条分支。`switch` 语句会决定哪一条分支应该被执行,这个流程被称作根据给定的值*切换switching*。
`switch` 语句必须是完备的。这就是说,每一个可能的值都必须至少有一个 case 分支与之对应。在某些不可能涵盖所有值的情况下,你可以使用默认(`default`)分支来涵盖其它所有没有对应的值,这个默认分支必须在 `switch` 语句的最后面。
@ -450,7 +450,7 @@ print("There are \(naturalCount) \(countedThings).")
我们可以使用元组在同一个 `switch` 语句中测试多个值。元组中的元素可以是值,也可以是区间。另外,使用下划线(`_`)来匹配所有可能的值。
下面的例子展示了如何使用一个 `(Int, Int)` 类型的元组来分类下图中的点(x, y)
下面的例子展示了如何使用一个 `(Int, Int)` 类型的元组来分类下图中的点 (x, y)
```swift
let somePoint = (1, 1)
@ -471,16 +471,16 @@ default:
![image](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/coordinateGraphSimple_2x.png)
在上面的例子中,`switch` 语句会判断某个点是否是原点(0, 0),是否在红色的 x 轴上,是否在橘黄色的 y 轴上是否在一个以原点为中心的4x4的蓝色矩形里或者在这个矩形外面。
在上面的例子中,`switch` 语句会判断某个点是否是原点 (0, 0),是否在红色的 x 轴上,是否在橘黄色的 y 轴上是否在一个以原点为中心的4x4的蓝色矩形里或者在这个矩形外面。
不像 C 语言Swift 允许多个 case 匹配同一个值。实际上,在这个例子中,点(0, 0)可以匹配所有_四个 case_。但是如果存在多个匹配那么只会执行第一个被匹配到的 case 分支。考虑点(0, 0)会首先匹配 `case (0, 0)`,因此剩下的能够匹配的分支都会被忽视掉。
不像 C 语言Swift 允许多个 case 匹配同一个值。实际上,在这个例子中,点 (0, 0)可以匹配所有_四个 case_。但是如果存在多个匹配那么只会执行第一个被匹配到的 case 分支。考虑点 (0, 0)会首先匹配 `case (0, 0)`,因此剩下的能够匹配的分支都会被忽视掉。
<a name="value_bindings"></a>
#### 值绑定Value Bindings
case 分支允许将匹配的值声明为临时常量或变量,并且在 case 分支体内使用 —— 这种行为被称为*值绑定*value binding因为匹配的值在 case 分支体内,与临时的常量或变量绑定。
下面的例子将下图中的点(x, y),使用 `(Int, Int)` 类型的元组表示,然后分类表示:
下面的例子将下图中的点 (x, y),使用 `(Int, Int)` 类型的元组表示,然后分类表示:
```swift
let anotherPoint = (2, 0)
@ -510,7 +510,7 @@ case let (x, y):
case 分支的模式可以使用 `where` 语句来判断额外的条件。
下面的例子把下图中的点(x, y)进行了分类:
下面的例子把下图中的点 (x, y)进行了分类:
```swift
let yetAnotherPoint = (1, -1)
@ -529,7 +529,7 @@ case let (x, y):
在上面的例子中,`switch` 语句会判断某个点是否在绿色的对角线 `x == y` 上,是否在紫色的对角线 `x == -y` 上,或者不在对角线上。
这三个 case 都声明了常量 `x``y` 的占位符,用于临时获取元组 `yetAnotherPoint` 的两个值。这两个常量被用作 `where` 语句的一部分,从而创建一个动态的过滤器(filter)。当且仅当 `where` 语句的条件为 `true` 时,匹配到的 case 分支才会被执行。
这三个 case 都声明了常量 `x``y` 的占位符,用于临时获取元组 `yetAnotherPoint` 的两个值。这两个常量被用作 `where` 语句的一部分,从而创建一个动态的过滤器filter。当且仅当 `where` 语句的条件为 `true` 时,匹配到的 case 分支才会被执行。
就像是值绑定中的例子,由于最后一个 case 分支匹配了余下所有可能的值,`switch` 语句就已经完备了,因此不需要再书写默认分支。
@ -614,12 +614,12 @@ print(puzzleOutput)
<a name="break_in_a_loop_statement"></a>
#### 循环语句中的 break
当在一个循环体中使用 `break` 时,会立刻中断该循环体的执行,然后跳转到表示循环体结束的大括号(`}`)后的第一行代码。不会再有本次循环的代码被执行,也不会再有下次的循环产生。
当在一个循环体中使用 `break` 时,会立刻中断该循环体的执行,然后跳转到表示循环体结束的大括号`}`后的第一行代码。不会再有本次循环的代码被执行,也不会再有下次的循环产生。
<a name="break_in_a_switch_statement"></a>
#### Switch 语句中的 break
当在一个 `switch` 代码块中使用 `break` 时,会立即中断该 `switch` 代码块的执行,并且跳转到表示 `switch` 代码块结束的大括号(`}`)后的第一行代码。
当在一个 `switch` 代码块中使用 `break` 时,会立即中断该 `switch` 代码块的执行,并且跳转到表示 `switch` 代码块结束的大括号`}`后的第一行代码。
这种特性可以被用来匹配或者忽略一个或多个分支。因为 Swift 的 `switch` 需要包含所有的分支而且不允许有为空的分支,有时为了使你的意图更明显,需要特意匹配或者忽略某个分支。那么当你想忽略某个分支时,可以在该分支内写上 `break` 语句。当那个分支被匹配到时,分支内的 `break` 语句立即结束 `switch` 代码块。
@ -659,7 +659,7 @@ if let integerValue = possibleIntegerValue {
在上面的例子中,想要把 `Character` 所有的的可能性都枚举出来是不现实的,所以使用 `default` 分支来包含所有上面没有匹配到字符的情况。由于这个 `default` 分支不需要执行任何动作,所以它只写了一条 `break` 语句。一旦落入到 `default` 分支中后,`break` 语句就完成了该分支的所有代码操作,代码继续向下,开始执行 `if let` 语句。
<a name="fallthrough"></a>
### 贯穿 (Fallthrough)
### 贯穿Fallthrough
在 Swift 里,`switch` 语句不会从上一个 case 分支跳转到下一个 case 分支中。相反,只要第一个匹配到的 case 分支完成了它需要执行的语句,整个 `switch` 代码块完成了它的执行。相比之下C 语言要求你显式地插入 `break` 语句到每个 case 分支的末尾来阻止自动落入到下一个 case 分支中。Swift 的这种避免默认落入到下一个分支中的特性意味着它的 `switch` 功能要比 C 语言的更加清晰和可预测,可以避免无意识地执行多个 case 分支从而引发的错误。
@ -696,7 +696,7 @@ print(description)
为了实现这个目的,你可以使用标签(*statement label*)来标记一个循环体或者条件语句,对于一个条件语句,你可以使用 `break` 加标签的方式,来结束这个被标记的语句。对于一个循环语句,你可以使用 `break` 或者 `continue` 加标签,来结束或者继续这条被标记语句的执行。
声明一个带标签的语句是通过在该语句的关键词的同一行前面放置一个标签,作为这个语句的前导关键字(introducor keyword),并且该标签后面跟随一个冒号。下面是一个针对 `while` 循环体的标签语法,同样的规则适用于所有的循环体和条件语句。
声明一个带标签的语句是通过在该语句的关键词的同一行前面放置一个标签,作为这个语句的前导关键字introducor keyword,并且该标签后面跟随一个冒号。下面是一个针对 `while` 循环体的标签语法,同样的规则适用于所有的循环体和条件语句。
```swift
label name: while condition {

View File

@ -145,7 +145,7 @@ greet(person: "Dave")
> 注意
>
> 严格上来说,虽然没有返回值被定义,`greet(person:)` 函数依然返回了值。没有定义返回类型的函数会返回一个特殊的 `Void` 值。它其实是一个空的元组,没有任何元素,可以写成()。
> 严格上来说,虽然没有返回值被定义,`greet(person:)` 函数依然返回了值。没有定义返回类型的函数会返回一个特殊的 `Void` 值。它其实是一个空的元组,没有任何元素,可以写成 `()`
被调用时,一个函数的返回值可以被忽略:
@ -246,7 +246,7 @@ if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
<a name="Function_Argument_Labels_and_Parameter_Names"></a>
## 函数参数标签和参数名称
每个函数参数都有一个*参数标签( argument label )*以及一个*参数名称( parameter name )*。参数标签在调用函数的时候使用;调用的时候需要将函数的参数标签写在对应的参数前面。参数名称在函数的实现中使用。默认情况下,函数参数使用参数名称来作为它们的参数标签。
每个函数参数都有一个*参数标签argument label*以及一个*参数名称parameter name*。参数标签在调用函数的时候使用;调用的时候需要将函数的参数标签写在对应的参数前面。参数名称在函数的实现中使用。默认情况下,函数参数使用参数名称来作为它们的参数标签。
```swift
func someFunction(firstParameterName: Int, secondParameterName: Int) {
@ -283,7 +283,7 @@ print(greet(person: "Bill", from: "Cupertino"))
<a name="omitting_argument_labels"></a>
### 忽略参数标签
如果你不希望为某个参数添加一个标签,可以使用一个下划线(`_`)来代替一个明确的参数标签。
如果你不希望为某个参数添加一个标签,可以使用一个下划线`_`来代替一个明确的参数标签。
```swift
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
@ -422,7 +422,7 @@ var mathFunction: (Int, Int) -> Int = addTwoInts
”定义一个叫做 `mathFunction` 的变量,类型是‘一个有两个 `Int` 型的参数并返回一个 `Int` 型的值的函数’,并让这个新变量指向 `addTwoInts` 函数”。
`addTwoInts``mathFunction` 有同样的类型,所以这个赋值过程在 Swift 类型检查(type-check)中是允许的。
`addTwoInts``mathFunction` 有同样的类型,所以这个赋值过程在 Swift 类型检查type-check中是允许的。
现在,你可以用 `mathFunction` 来调用被赋值的函数了:

View File

@ -246,7 +246,7 @@ let strings = numbers.map {
> 注意
>
> 字典 `digitNames` 下标后跟着一个叹号(`!`因为字典下标返回一个可选值optional value表明该键不存在时会查找失败。在上例中由于可以确定 `number % 10` 总是 `digitNames` 字典的有效下标,因此叹号可以用于强制解包 (force-unwrap) 存储在下标的可选类型的返回值中的 `String` 类型的值。
> 字典 `digitNames` 下标后跟着一个叹号(`!`因为字典下标返回一个可选值optional value表明该键不存在时会查找失败。在上例中由于可以确定 `number % 10` 总是 `digitNames` 字典的有效下标,因此叹号可以用于强制解包force-unwrap存储在下标的可选类型的返回值中的 `String` 类型的值。
`digitNames` 字典中获取的字符串被添加到 `output` 的*前部*,逆序建立了一个字符串版本的数字。(在表达式 `number % 10` 中,如果 `number``16`,则返回 `6``58` 返回 `8``510` 返回 `0`。)

View File

@ -118,7 +118,7 @@ let someVideoMode = VideoMode()
<a name="accessing_properties"></a>
### 属性访问
通过使用*点语法*,你可以访问实例的属性。其语法规则是,实例名后面紧跟属性名,两者通过点号(`.`)连接:
通过使用*点语法*,你可以访问实例的属性。其语法规则是,实例名后面紧跟属性名,两者通过点号`.`连接:
```swift
print("The width of someResolution is \(someResolution.width)")

View File

@ -1,4 +1,4 @@
# 属性 (Properties)
# 属性Properties
---
> 1.0

View File

@ -32,7 +32,7 @@
结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一。在 Objective-C 中,类是唯一能定义方法的类型。但在 Swift 中,你不仅能选择是否要定义一个类/结构体/枚举,还能灵活地在你创建的类型(类/结构体/枚举)上定义方法。
<a name="instance_methods"></a>
## 实例方法 (Instance Methods)
## 实例方法Instance Methods
*实例方法*是属于某个特定类、结构体或者枚举类型实例的方法。实例方法提供访问和修改实例属性的方法或提供与实例目的相关的功能,并以此来支撑实例的功能。实例方法的语法与函数完全一致,详情参见[函数](./06_Functions.md)。
@ -117,7 +117,7 @@ if somePoint.isToTheRightOfX(1.0) {
结构体和枚举是*值类型*。默认情况下,值类型的属性不能在它的实例方法中被修改。
但是,如果你确实需要在某个特定的方法中修改结构体或者枚举的属性,你可以为这个方法选择 `可变(mutating)`行为,然后就可以从其方法内部改变它的属性;并且这个方法做的任何改变都会在方法执行结束时写回到原始结构中。方法还可以给它隐含的 `self` 属性赋予一个全新的实例,这个新实例在方法结束时会替换现存实例。
但是,如果你确实需要在某个特定的方法中修改结构体或者枚举的属性,你可以为这个方法选择 `可变mutating`行为,然后就可以从其方法内部改变它的属性;并且这个方法做的任何改变都会在方法执行结束时写回到原始结构中。方法还可以给它隐含的 `self` 属性赋予一个全新的实例,这个新实例在方法结束时会替换现存实例。
要使用 `可变`方法,将关键字 `mutating` 放到方法的 `func` 关键字之前就可以了:

View File

@ -173,7 +173,7 @@ let veryGreen = Color(0.0, 1.0, 0.0)
<a name="initializer_parameters_without_external_names"></a>
### 不带参数标签的构造器参数
如果你不希望为构造器的某个参数提供参数标签,你可以使用下划线(`_`)来显式描述它的外部名,以此重写上面所说的默认行为。
如果你不希望为构造器的某个参数提供参数标签,你可以使用下划线`_`来显式描述它的外部名,以此重写上面所说的默认行为。
下面是之前 `Celsius` 例子的扩展,跟之前相比添加了一个带有 `Double` 类型参数的构造器,其外部名用 `_` 代替:
@ -729,7 +729,7 @@ for item in breakfastList {
如果一个类、结构体或枚举类型的对象,在构造过程中有可能失败,则为其定义一个可失败构造器是很有用的。这里所指的“失败” 指的是,如给构造器传入无效的参数值,或缺少某种所需的外部资源,又或是不满足某种必要的条件等。
为了妥善处理这种构造过程中可能会失败的情况。你可以在一个类,结构体或是枚举类型的定义中,添加一个或多个可失败构造器。其语法为在 `init` 关键字后面添加问号 (`init?`)
为了妥善处理这种构造过程中可能会失败的情况。你可以在一个类,结构体或是枚举类型的定义中,添加一个或多个可失败构造器。其语法为在 `init` 关键字后面添加问号`init?`
> 注意
>
@ -808,7 +808,7 @@ if anonymousCreature == nil {
你可以通过一个带一个或多个参数的可失败构造器来获取枚举类型中特定的枚举成员。如果提供的参数无法匹配任何枚举成员,则构造失败。
下例中,定义了一个名为 `TemperatureUnit` 的枚举类型。其中包含了三个可能的枚举成员(`Kelvin``Celsius``Fahrenheit`),以及一个根据 `Character` 值找出所对应的枚举成员的可失败构造器:
下例中,定义了一个名为 `TemperatureUnit` 的枚举类型。其中包含了三个可能的枚举成员`Kelvin``Celsius``Fahrenheit`,以及一个根据 `Character` 值找出所对应的枚举成员的可失败构造器:
```swift
enum TemperatureUnit {

View File

@ -338,7 +338,7 @@ func findIndex<T>(of valueToFind: T, in array:[T]) -> Int? {
上面所写的函数无法通过编译。问题出在相等性检查上,即 "`if value == valueToFind`"。不是所有的 Swift 类型都可以用等式符(`==`)进行比较。比如说,如果你创建一个自定义的类或结构体来表示一个复杂的数据模型,那么 Swift 无法猜到对于这个类或结构体而言“相等”意味着什么。正因如此,这部分代码无法保证适用于每个可能的类型 `T`,当你试图编译这部分代码时会出现相应的错误。
不过所有的这些并不会让我们无从下手。Swift 标准库中定义了一个 `Equatable` 协议,该协议要求任何遵循该协议的类型必须实现等式符(`==`)及不等符(`!=`),从而能对该类型的任意两个值进行比较。所有的 Swift 标准类型自动支持 `Equatable` 协议。
不过所有的这些并不会让我们无从下手。Swift 标准库中定义了一个 `Equatable` 协议,该协议要求任何遵循该协议的类型必须实现等式符(`==`)及不等符`!=`,从而能对该类型的任意两个值进行比较。所有的 Swift 标准类型自动支持 `Equatable` 协议。
任何 `Equatable` 类型都可以安全地使用在 `findIndex(of:in:)` 函数中,因为其保证支持等式操作符。为了说明这个事实,当你定义一个函数时,你可以定义一个 `Equatable` 类型约束作为类型参数定义的一部分:
@ -746,7 +746,7 @@ extension Container {
- 在尖括号中的泛型参数 `Indices`,必须是符合标准库中的 `Sequence` 协议的类型。
- 下标使用的单一的参数,`indices`,必须是 `Indices` 的实例。
- 泛型 `where` 子句要求 SequenceIndices的迭代器其所有的元素都是 `Int` 类型。这样就能确保在序列Sequence中的索引和容器(Container)里面的索引类型是一致的。
- 泛型 `where` 子句要求 SequenceIndices的迭代器其所有的元素都是 `Int` 类型。这样就能确保在序列Sequence中的索引和容器Container里面的索引类型是一致的。
综合一下,这些约束意味着,传入到 `indices` 下标,是一个整型的序列。