From 16386d375c3520414a81b132d032afed08043df0 Mon Sep 17 00:00:00 2001 From: 100mango <100mango@users.noreply.github.com> Date: Sun, 28 Jun 2015 10:48:05 +0800 Subject: [PATCH 01/50] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=97=AD=E5=8C=85?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8FClosure=20Expressions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 旧版本: sorted function Swift2.0: sort(_:) method --- source/chapter2/07_Closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/chapter2/07_Closures.md b/source/chapter2/07_Closures.md index 093a113d..9ccd932e 100755 --- a/source/chapter2/07_Closures.md +++ b/source/chapter2/07_Closures.md @@ -41,7 +41,7 @@ Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进 闭包表达式是一种利用简洁语法构建内联闭包的方式。 闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。 -下面闭包表达式的例子通过使用几次迭代展示了`sorted`函数定义和语法优化的方式。 +下面闭包表达式的例子通过使用几次迭代展示了`sort(_:)`方法定义和语法优化的方式。 每一次迭代都用更简洁的方式描述了相同的功能。 From 3d24bfd965fbf7642b1a611c63243f695e85dd07 Mon Sep 17 00:00:00 2001 From: 100mango <100mango@users.noreply.github.com> Date: Sun, 28 Jun 2015 11:38:52 +0800 Subject: [PATCH 02/50] =?UTF-8?q?=E6=9B=B4=E6=96=B0sort=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.修订润色,将Sorted修改为Sort. 2.增添缺少的The original array is not modified by the sort(_:) method翻译 --- source/chapter2/07_Closures.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/chapter2/07_Closures.md b/source/chapter2/07_Closures.md index 093a113d..728c9416 100755 --- a/source/chapter2/07_Closures.md +++ b/source/chapter2/07_Closures.md @@ -45,10 +45,10 @@ Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进 每一次迭代都用更简洁的方式描述了相同的功能。 -### sorted 函数(The Sorted Function) +### sort 函数(The Sort Function) -Swift 标准库提供了`sorted`函数,会根据您提供的基于输出类型排序的闭包函数将已知类型数组中的值进行排序。 -一旦排序完成,函数会返回一个与原数组大小相同的新数组,该数组中包含已经正确排序的同类型元素。 +Swift 标准库提供了名为`sort`的函数,会根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。 +一旦排序完成,`sort(_:)`方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。原数组不会被`sort(_:)`方法修改。 下面的闭包表达式示例使用`sorted`函数对一个`String`类型的数组进行字母逆序排序,以下是初始数组值: From 9e6fb79df5170676b6092187a90c0c35d5fd53b0 Mon Sep 17 00:00:00 2001 From: 100mango <100mango@users.noreply.github.com> Date: Sun, 28 Jun 2015 12:44:34 +0800 Subject: [PATCH 03/50] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BF=AE=E8=AE=A2=20so?= =?UTF-8?q?rt=E5=87=BD=E6=95=B0=20=E5=B0=8F=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/07_Closures.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/chapter2/07_Closures.md b/source/chapter2/07_Closures.md index 093a113d..2a006e82 100755 --- a/source/chapter2/07_Closures.md +++ b/source/chapter2/07_Closures.md @@ -50,26 +50,26 @@ Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进 Swift 标准库提供了`sorted`函数,会根据您提供的基于输出类型排序的闭包函数将已知类型数组中的值进行排序。 一旦排序完成,函数会返回一个与原数组大小相同的新数组,该数组中包含已经正确排序的同类型元素。 -下面的闭包表达式示例使用`sorted`函数对一个`String`类型的数组进行字母逆序排序,以下是初始数组值: +下面的闭包表达式示例使用`sort(_:)`方法对一个String类型的数组进行字母逆序排序,以下是初始数组值: ```swift let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] ``` -`sorted`函数需要传入两个参数: +`sort(_:)`方法需要传入两个参数: * 已知类型的数组 -* 闭包函数,该闭包函数需要传入与数组类型相同的两个值,并返回一个布尔类型值来告诉`sorted`函数当排序结束后传入的第一个参数排在第二个参数前面还是后面。如果第一个参数值出现在第二个参数值前面,排序闭包函数需要返回`true`,反之返回`false`。 +* 闭包函数,该闭包函数需要传入与数组元素类型相同的两个值,并返回一个布尔类型值来表明当排序结束后传入的第一个参数排在第二个参数前面还是后面。如果第一个参数值出现在第二个参数值前面,排序闭包函数需要返回`true`,反之返回`false`。 该例子对一个`String`类型的数组进行排序,因此排序闭包函数类型需为`(String, String) -> Bool`。 -提供排序闭包函数的一种方式是撰写一个符合其类型要求的普通函数,并将其作为`sort`函数的第二个参数传入: +提供排序闭包函数的一种方式是撰写一个符合其类型要求的普通函数,并将其作为`ssort(_:)`方法的参数传入: ```swift func backwards(s1: String, s2: String) -> Bool { return s1 > s2 } -var reversed = sorted(names, backwards) +var reversed = names.sort(backwards) // reversed 为 ["Ewa", "Daniella", "Chris", "Barry", "Alex"] ``` From aa8a3a6ac6c762bf0507d3845fdbd09eb4111ab8 Mon Sep 17 00:00:00 2001 From: 100mango <100mango@users.noreply.github.com> Date: Sun, 28 Jun 2015 13:07:00 +0800 Subject: [PATCH 04/50] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=AD=E5=8C=85?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=AF=AD=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/07_Closures.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/chapter2/07_Closures.md b/source/chapter2/07_Closures.md index 093a113d..bd3696ab 100755 --- a/source/chapter2/07_Closures.md +++ b/source/chapter2/07_Closures.md @@ -99,7 +99,7 @@ var reversed = sorted(names, backwards) 下面的例子展示了之前`backwards`函数对应的闭包表达式版本的代码: ```swift -reversed = sorted(names, { (s1: String, s2: String) -> Bool in +reversed = names.sort({ (s1: String, s2: String) -> Bool in return s1 > s2 }) ``` @@ -114,10 +114,10 @@ reversed = sorted(names, { (s1: String, s2: String) -> Bool in 因为这个闭包的函数体部分如此短以至于可以将其改写成一行代码: ```swift -reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } ) +reversed = names.sort( { (s1: String, s2: String) -> Bool in return s1 > s2 } ) ``` -这说明`sorted`函数的整体调用保持不变,一对圆括号仍然包裹住了函数中整个参数集合。而其中一个参数现在变成了内联闭包(相比于`backwards`版本的代码)。 +这说明`sort(_:)`方法的整体调用保持不变,一对圆括号仍然包裹住了函数中整个参数集合。而其中一个参数现在变成了内联闭包(相比于`backwards`版本的代码) ### 根据上下文推断类型(Inferring Type From Context) From 5e33251e5d9f7c6d4505456f9f75dc7a25975b9b Mon Sep 17 00:00:00 2001 From: 100mango <100mango@users.noreply.github.com> Date: Sun, 28 Jun 2015 13:45:37 +0800 Subject: [PATCH 05/50] =?UTF-8?q?=E4=BF=AE=E8=AE=A2Inferring=20Type=20From?= =?UTF-8?q?=20Context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.修订sort方法 2.增加未翻译部分 --- source/chapter2/07_Closures.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/chapter2/07_Closures.md b/source/chapter2/07_Closures.md index 093a113d..da022838 100755 --- a/source/chapter2/07_Closures.md +++ b/source/chapter2/07_Closures.md @@ -122,16 +122,18 @@ reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } ### 根据上下文推断类型(Inferring Type From Context) -因为排序闭包函数是作为`sorted`函数的参数进行传入的,Swift可以推断其参数和返回值的类型。 +因为排序闭包函数是作为`sort(_:)`方法的参数进行传入的,Swift可以推断其参数和返回值的类型。 `sorted`期望第二个参数是类型为`(String, String) -> Bool`的函数,因此实际上`String`,`String`和`Bool`类型并不需要作为闭包表达式定义中的一部分。 因为所有的类型都可以被正确推断,返回箭头 (`->`) 和围绕在参数周围的括号也可以被省略: ```swift -reversed = sorted(names, { s1, s2 in return s1 > s2 } ) +reversed = names.sort( { s1, s2 in return s1 > s2 } ) ``` 实际上任何情况下,通过内联闭包表达式构造的闭包作为参数传递给函数时,都可以推断出闭包的参数和返回值类型,这意味着您几乎不需要利用完整格式构造任何内联闭包。 +然而您仍然可以明确写出有着完整格式的闭包。如果完整格式的闭包能够提高代码的可读性我,我们建议采取这种形式。而在`sort(_:)`方法这个例子里,闭包的目的就是排序,读者能够推测除这个闭包是用于字符串处理的,因为这个闭包是为了处理字符串数组的排序。 + ### 单表达式闭包隐式返回(Implicit Return From Single-Expression Clossures) From 56a3be66b2039d2b0ae8cad791ec7aa39a2b4eec Mon Sep 17 00:00:00 2001 From: 100mango <100mango@users.noreply.github.com> Date: Sun, 28 Jun 2015 13:51:07 +0800 Subject: [PATCH 06/50] =?UTF-8?q?=E4=BF=AE=E6=94=B9Inferring=20Type=20From?= =?UTF-8?q?=20Context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/07_Closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/chapter2/07_Closures.md b/source/chapter2/07_Closures.md index da022838..806f321e 100755 --- a/source/chapter2/07_Closures.md +++ b/source/chapter2/07_Closures.md @@ -132,7 +132,7 @@ reversed = names.sort( { s1, s2 in return s1 > s2 } ) 实际上任何情况下,通过内联闭包表达式构造的闭包作为参数传递给函数时,都可以推断出闭包的参数和返回值类型,这意味着您几乎不需要利用完整格式构造任何内联闭包。 -然而您仍然可以明确写出有着完整格式的闭包。如果完整格式的闭包能够提高代码的可读性我,我们建议采取这种形式。而在`sort(_:)`方法这个例子里,闭包的目的就是排序,读者能够推测除这个闭包是用于字符串处理的,因为这个闭包是为了处理字符串数组的排序。 +然而您仍然可以明确写出有着完整格式的闭包。如果完整格式的闭包能够提高代码的可读性,则可以采用完整格式的闭包。而在`sort(_:)`方法这个例子里,闭包的目的就是排序,读者能够推测除这个闭包是用于字符串处理的,因为这个闭包是为了处理字符串数组的排序。 ### 单表达式闭包隐式返回(Implicit Return From Single-Expression Clossures) From 359d9acb94c95d8ccb9262be90e83a02e160018c Mon Sep 17 00:00:00 2001 From: 100mango <100mango@users.noreply.github.com> Date: Sun, 28 Jun 2015 14:05:44 +0800 Subject: [PATCH 07/50] =?UTF-8?q?=E4=BF=AE=E8=AE=A2Implicit=20Return=20Fro?= =?UTF-8?q?m=20Single-Expression=20Clossures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/07_Closures.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/chapter2/07_Closures.md b/source/chapter2/07_Closures.md index 806f321e..f3324d16 100755 --- a/source/chapter2/07_Closures.md +++ b/source/chapter2/07_Closures.md @@ -140,10 +140,10 @@ reversed = names.sort( { s1, s2 in return s1 > s2 } ) 单行表达式闭包可以通过隐藏`return`关键字来隐式返回单行表达式的结果,如上版本的例子可以改写为: ```swift -reversed = sorted(names, { s1, s2 in s1 > s2 } ) +reversed = names.sort( { s1, s2 in s1 > s2 } ) ``` -在这个例子中,`sorted`函数的第二个参数函数类型明确了闭包必须返回一个`Bool`类型值。 +在这个例子中,`sort(_:)`方法的第二个参数函数类型明确了闭包必须返回一个`Bool`类型值。 因为闭包函数体只包含了一个单一表达式 (`s1 > s2`),该表达式返回`Bool`类型值,因此这里没有歧义,`return`关键字可以省略。 From cf51cad41a96f6f868d39394ddbdcfb4fdcf15cc Mon Sep 17 00:00:00 2001 From: 100mango <100mango@users.noreply.github.com> Date: Sun, 28 Jun 2015 14:26:25 +0800 Subject: [PATCH 08/50] =?UTF-8?q?=E4=BF=AE=E8=AE=A2sorted,()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.sorted -> sort 2.() -> Void --- source/chapter2/07_Closures.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/chapter2/07_Closures.md b/source/chapter2/07_Closures.md index f3324d16..7f7969de 100755 --- a/source/chapter2/07_Closures.md +++ b/source/chapter2/07_Closures.md @@ -155,7 +155,7 @@ Swift 自动为内联函数提供了参数名称缩写功能,您可以直接 `in`关键字也同样可以被省略,因为此时闭包表达式完全由闭包函数体构成: ```swift -reversed = sorted(names, { $0 > $1 } ) +reversed = names.sort( { $0 > $1 } ) ``` 在这个例子中,`$0`和`$1`表示闭包中第一个和第二个`String`类型的参数。 @@ -165,11 +165,11 @@ reversed = sorted(names, { $0 > $1 } ) 实际上还有一种更简短的方式来撰写上面例子中的闭包表达式。 Swift 的`String`类型定义了关于大于号 (`>`) 的字符串实现,其作为一个函数接受两个`String`类型的参数并返回`Bool`类型的值。 -而这正好与`sorted`函数的第二个参数需要的函数类型相符合。 +而这正好与`sort(_:)`方法的第二个参数需要的函数类型相符合。 因此,您可以简单地传递一个大于号,Swift可以自动推断出您想使用大于号的字符串函数实现: ```swift -reversed = sorted(names, >) +reversed = names.sort(>) ``` 更多关于运算符表达式的内容请查看 [运算符函数](../chapter2/24_Advanced_Operators.html#operator_functions)。 @@ -182,7 +182,7 @@ reversed = sorted(names, >) 尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。 ```swift -func someFunctionThatTakesAClosure(closure: () -> ()) { +func someFunctionThatTakesAClosure(closure: () -> Void) { // 函数体部分 } @@ -203,7 +203,7 @@ someFunctionThatTakesAClosure() { 在上例中作为`sorted`函数参数的字符串排序闭包可以改写为: ```swift -reversed = sorted(names) { $0 > $1 } +reversed = names.sort() { $0 > $1 } ``` 当闭包非常长以至于不能在一行中进行书写时,尾随闭包变得非常有用。 @@ -283,7 +283,7 @@ Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的 每次调用`incrementor`时,其会以`amount`作为增量增加`runningTotal`的值。 ```swift -func makeIncrementor(forIncrement amount: Int) -> () -> Int { +func makeIncrementor(forIncrement amount: Int) -> Void -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount @@ -293,7 +293,7 @@ func makeIncrementor(forIncrement amount: Int) -> () -> Int { } ``` -`makeIncrementor`返回类型为`() -> Int`。 +`makeIncrementor`返回类型为`Void -> Int`。 这意味着其返回的是一个函数,而不是一个简单类型值。 该函数在每次调用时不接受参数只返回一个`Int`类型的值。 关于函数返回其他函数的内容,请查看[函数类型作为返回类型](../chapter2/06_Functions.html#function_types_as_return_types)。 From e49e55db0080a6a231b8a8531c2290a1bcc4b993 Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Sun, 28 Jun 2015 16:38:24 +0800 Subject: [PATCH 09/50] patterns updated test --- source/chapter3/07_Patterns.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 3448a392..49a3ff9b 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -16,6 +16,8 @@ 模式(pattern)代表了单个值或者复合值的结构。例如,元组`(1, 2)`的结构是逗号分隔的,包含两个元素的列表。因为模式代表一种值的结构,而不是特定的某个值,你可以把模式和各种同类型的值匹配起来。比如,`(x, y)`可以匹配元组`(1, 2)`,以及任何含两个元素的元组。除了将模式与一个值匹配外,你可以从合成值中提取出部分或全部,然后分别把各个部分和一个常量或变量绑定起来。 +swift中有2种模式的基本类型: + 在Swift中,模式出现在变量和常量的声明(在它们的左侧),`for-in`语句和`switch`语句(在它们的case标签)中。尽管任何模式都可以出现在`switch`语句的case标签中,但在其他情况下,只有通配符模式(wildcard pattern),标识符模式(identifier pattern)和包含这两种模式的模式才能出现。 你可以为通配符模式(wildcard pattern),标识符模式(identifier pattern)和元组模式(tuple pattern)指定类型注释,用来限制这种模式只匹配某种类型的值。 @@ -179,4 +181,4 @@ default: ``` > 表达式模式语法 -> *表达式模式* → [*表达式*](..\chapter3\04_Expressions.html#expression) \ No newline at end of file +> *表达式模式* → [*表达式*](..\chapter3\04_Expressions.html#expression) From 4a35d8c35bc50df741ebe2e03ed7b34c316d31cd Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Sun, 28 Jun 2015 17:19:15 +0800 Subject: [PATCH 10/50] updated 17:18, 6/28/2015 --- source/chapter3/07_Patterns.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 49a3ff9b..b9fcb902 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -16,7 +16,11 @@ 模式(pattern)代表了单个值或者复合值的结构。例如,元组`(1, 2)`的结构是逗号分隔的,包含两个元素的列表。因为模式代表一种值的结构,而不是特定的某个值,你可以把模式和各种同类型的值匹配起来。比如,`(x, y)`可以匹配元组`(1, 2)`,以及任何含两个元素的元组。除了将模式与一个值匹配外,你可以从合成值中提取出部分或全部,然后分别把各个部分和一个常量或变量绑定起来。 -swift中有2种模式的基本类型: +swift中有2个基本的模式种类:一类能成功和任何值的类型相匹配,另一类在运行时(runtime)和某特定值匹配时可能会失败。 + +第一类模式用于析构简单变量,常量和可选绑定中的值。此类模式包括通配符模式,标识符模式,以及任何包含了它们的值绑定模式或者元祖模式。你可以为这些模式指定一个类型注释(type annotation)来限制它们只能匹配某种特定类型的值。 + +第二类模式用于全模式匹配,这种情况下你用来相比较的值在运行时可能还不存在。此类模式包括枚举用例模式,可选模式,表达式模式和类型转换模式。你在`switch`语句的case标签中,`do`语句的`catch`从句中,或者在`if, while, guard`和`for-in`语句的case条件句中使用这类模式。 在Swift中,模式出现在变量和常量的声明(在它们的左侧),`for-in`语句和`switch`语句(在它们的case标签)中。尽管任何模式都可以出现在`switch`语句的case标签中,但在其他情况下,只有通配符模式(wildcard pattern),标识符模式(identifier pattern)和包含这两种模式的模式才能出现。 From cc27f4fccb441d372800758af9c3e3fc6373f30f Mon Sep 17 00:00:00 2001 From: chenYuheng Date: Sun, 28 Jun 2015 21:09:11 +0800 Subject: [PATCH 11/50] =?UTF-8?q?1.=E4=BF=AE=E6=94=B9=E4=BA=86=E8=8E=B7?= =?UTF-8?q?=E5=8F=96rawValue=E7=9A=84=E6=96=B9=E6=B3=95=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=202.=E4=BF=AE=E6=94=B9=E4=BA=86=E9=83=A8=E5=88=86=E5=92=8C?= =?UTF-8?q?=E6=96=87=E6=9C=AC=E6=84=8F=E6=80=9D=E4=B8=8D=E7=AC=A6=E7=9A=84?= =?UTF-8?q?=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/19_Nested_Types.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/chapter2/19_Nested_Types.md b/source/chapter2/19_Nested_Types.md index 0db7d1da..bd03302e 100755 --- a/source/chapter2/19_Nested_Types.md +++ b/source/chapter2/19_Nested_Types.md @@ -41,7 +41,7 @@ struct BlackjackCard { case .Jack, .Queen, .King: return Values(first: 10, second: nil) default: - return Values(first: self.toRaw(), second: nil) + return Values(first: self.rawValue, second: nil) } } } @@ -49,7 +49,7 @@ struct BlackjackCard { // BlackjackCard 的属性和方法 let rank: Rank, suit: Suit var description: String { - var output = "suit is \(suit.toRaw())," + var output = "suit is \(suit.rawValue)," output += " value is \(rank.values.first)" if let second = rank.values.second { output += " or \(second)" @@ -63,12 +63,12 @@ struct BlackjackCard { 枚举型的`Rank`用来描述扑克牌从`Ace`~10,`J`,`Q`,`K`,13张牌,并分别用一个`Int`类型的值表示牌的面值。(这个`Int`类型的值不适用于`Ace`,`J`,`Q`,`K`的牌)。 -如上文所提到的,枚举型`Rank`在自己内部定义了一个嵌套结构体`Values`。这个结构体包含两个变量,只有`Ace`有两个数值,其余牌都只有一个数值。结构体`Values`中定义的两个属性: +如上文所提到的,枚举型`Rank`在自己内部定义了一个嵌套结构体`Values`。在这个结构体中,只有`Ace`有两个数值,其余牌都只有一个数值。结构体`Values`中定义的两个属性: `first`, 为` Int` `second`, 为 `Int?`, 或 “optional `Int`” -`Rank`定义了一个计算属性`values`,这个计算属性会根据牌的面值,用适当的数值去初始化`Values`实例,并赋值给`values`。对于`J`,`Q`,`K`,`Ace`会使用特殊数值,对于数字面值的牌使用`Int`类型的值。 +`Rank`定义了一个计算属性`values`,它将会返回一个结构体`Values`的实例。这个计算属性会根据牌的面值,用适当的数值去初始化`Values`实例,并赋值给`values`。对于`J`,`Q`,`K`,`Ace`会使用特殊数值,对于数字面值的牌使用`Int`类型的值。 `BlackjackCard`结构体自身有两个属性—`rank`与`suit`,也同样定义了一个计算属性`description`,`description`属性用`rank`和`suit`的中内容来构建对这张扑克牌名字和数值的描述,并用可选类型`second`来检查是否存在第二个值,若存在,则在原有的描述中增加对第二数值的描述。 @@ -88,9 +88,9 @@ println("theAceOfSpades: \(theAceOfSpades.description)") 在外部对嵌套类型的引用,以被嵌套类型的名字为前缀,加上所要引用的属性名: ```swift -let heartsSymbol = BlackjackCard.Suit.Hearts.toRaw() +let heartsSymbol = BlackjackCard.Suit.Hearts.rawValue // 红心的符号 为 "♡" ``` -对于上面这个例子,这样可以使`Suit`, `Rank`, 和 `Values`的名字尽可能的短,因为它们的名字会自然的由被定义的上下文来限定。 +对于上面这个例子,这样可以使`Suit`, `Rank`, 和 `Values`的名字尽可能的短,因为它们的名字会自然的由定义它们的上下文来限定。 From d849ef96b352481439d9a41e8cf1b30ee137553c Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Sun, 28 Jun 2015 21:20:53 +0800 Subject: [PATCH 12/50] patterns_21:20_06/28/2015 --- source/chapter3/07_Patterns.md | 70 ++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index b9fcb902..28e2a23a 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -11,6 +11,7 @@ - [值绑定模式(Value-Binding Pattern)](#value-binding_pattern) - [元组模式(Tuple Pattern)](#tuple_pattern) - [枚举用例模式(Enumeration Case Pattern)](#enumeration_case_pattern) +- [可选模式(Optional Patterns)](#optional_patterns) - [类型转换模式(Type-Casting Patterns)](#type-casting_patterns) - [表达式模式(Expression Pattern)](#expression_pattern) @@ -18,20 +19,17 @@ swift中有2个基本的模式种类:一类能成功和任何值的类型相匹配,另一类在运行时(runtime)和某特定值匹配时可能会失败。 -第一类模式用于析构简单变量,常量和可选绑定中的值。此类模式包括通配符模式,标识符模式,以及任何包含了它们的值绑定模式或者元祖模式。你可以为这些模式指定一个类型注释(type annotation)来限制它们只能匹配某种特定类型的值。 +第一类模式用于解构简单变量,常量和可选绑定中的值。此类模式包括通配符模式(wildcard pattern),标识符模式(identifier pattern),以及任何包含了它们的值绑定模式(value binding pattern)或者元祖模式(tuple pattern)。你可以为这类模式指定一个类型注释(type annotation)来限制它们只能匹配某种特定类型的值。 第二类模式用于全模式匹配,这种情况下你用来相比较的值在运行时可能还不存在。此类模式包括枚举用例模式,可选模式,表达式模式和类型转换模式。你在`switch`语句的case标签中,`do`语句的`catch`从句中,或者在`if, while, guard`和`for-in`语句的case条件句中使用这类模式。 -在Swift中,模式出现在变量和常量的声明(在它们的左侧),`for-in`语句和`switch`语句(在它们的case标签)中。尽管任何模式都可以出现在`switch`语句的case标签中,但在其他情况下,只有通配符模式(wildcard pattern),标识符模式(identifier pattern)和包含这两种模式的模式才能出现。 - -你可以为通配符模式(wildcard pattern),标识符模式(identifier pattern)和元组模式(tuple pattern)指定类型注释,用来限制这种模式只匹配某种类型的值。 - > 模式(Patterns) 语法 > *模式* → [*通配符模式*](..\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#value_binding_pattern) > *模式* → [*元组模式*](..\chapter3\07_Patterns.html#tuple_pattern) [*类型注解*](..\chapter3\03_Types.html#type_annotation) _可选_ > *模式* → [*enum-case-pattern*](..\chapter3\07_Patterns.html#enum_case_pattern) +> *模式* → [*可选模式*](..\chapter3\07_Patterns.html#optional_pattern) [*类型注解*](..\chapter3\03_Types.html#optional_type) _可选_ > *模式* → [*type-casting-pattern*](..\chapter3\07_Patterns.html#type_casting_pattern) > *模式* → [*表达式模式*](..\chapter3\07_Patterns.html#expression_pattern) @@ -42,7 +40,7 @@ swift中有2个基本的模式种类:一类能成功和任何值的类型相 ```swift for _ in 1...3 { - // Do something three times. +// Do something three times. } ``` @@ -75,9 +73,9 @@ let someValue = 42 ```swift let point = (3, 2) switch point { - // Bind x and y to the elements of point. +// Bind x and y to the elements of point. case let (x, y): - println("The point is at (\(x), \(y)).") +println("The point is at (\(x), \(y)).") } // prints "The point is at (3, 2).” ``` @@ -100,7 +98,7 @@ case let (x, y): let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)] // This code isn't valid. for (x, 0) in points { - /* ... */ +/* ... */ } ``` @@ -127,6 +125,46 @@ let (a): Int = 2 // a: Int = 2 > 枚举用例模式语法 > *enum-case-pattern* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) _可选_ **.** [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*元组模式*](..\chapter3\07_Patterns.html#tuple_pattern) _可选_ + + + +## 可选模式(Optional Pattern) + +可选模式 封装在一个`Some(T)` + +可选模式由一个标识符模式和紧随其后的一个问号组成,在某种情况下表现为枚举用例模式。 + +由于可选模式是`optionan`和`ImplicitlyUnwrappedOptional`枚举用例模式的语法糖,下面的两种写法一样的: + +```swift +let someOptional: Int? = 42 +// Match using an enumeration case pattern +if case .Some(let x) = someOptional { + print(x) +} + +// Match using an optional pattern +if case let x? = someOptional { + print(x) +} +``` + +可选模式在`for-in`语句提供了在一个元素是可选类型的数组中迭代的简便的方式,只为数组中的非空元素执行循环。 + +```swift +let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5] +// Match only non-nil values +for case let number? in arrayOfOptinalInts { + print("Found a \(number)") +} +//Found a 2 +//Found a 3 +//Found a 5 + +``` +> 可选模式语法 +> *optional-pattern* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) ? + ## 类型转换模式(Type-Casting Patterns) @@ -157,11 +195,11 @@ let (a): Int = 2 // a: Int = 2 let point = (1, 2) switch point { case (0, 0): - println("(0, 0) is at the origin.") +println("(0, 0) is at the origin.") case (-2...2, -2...2): - println("(\(point.0), \(point.1)) is near the origin.") +println("(\(point.0), \(point.1)) is near the origin.") default: - println("The point is at (\(point.0), \(point.1)).") +println("The point is at (\(point.0), \(point.1)).") } // prints "(1, 2) is near the origin.” ``` @@ -171,15 +209,15 @@ default: ```swift // Overload the ~= operator to match a string with an integer func ~=(pattern: String, value: Int) -> Bool { - return pattern == "\(value)" +return pattern == "\(value)" } switch point { case ("0", "0"): - println("(0, 0) is at the origin.") +println("(0, 0) is at the origin.") case ("-2...2", "-2...2"): - println("(\(point.0), \(point.1)) is near the origin.") +println("(\(point.0), \(point.1)) is near the origin.") default: - println("The point is at (\(point.0), \(point.1)).") +println("The point is at (\(point.0), \(point.1)).") } // prints "(1, 2) is near the origin.” ``` From ca44d06f29216c2bb9027a64cafb1f6c9d2939fa Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Mon, 29 Jun 2015 12:57:36 +0800 Subject: [PATCH 13/50] patterns_12:57_06/29/2015_Preliminary --- source/chapter3/07_Patterns.md | 38 +++++++++++++++------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 28e2a23a..0795f26f 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -11,15 +11,15 @@ - [值绑定模式(Value-Binding Pattern)](#value-binding_pattern) - [元组模式(Tuple Pattern)](#tuple_pattern) - [枚举用例模式(Enumeration Case Pattern)](#enumeration_case_pattern) -- [可选模式(Optional Patterns)](#optional_patterns) -- [类型转换模式(Type-Casting Patterns)](#type-casting_patterns) +- [可选模式(Optional Patterns)](#optional_pattern) +- [类型转换模式(Type-Casting Patterns)](#type-casting_pattern) - [表达式模式(Expression Pattern)](#expression_pattern) -模式(pattern)代表了单个值或者复合值的结构。例如,元组`(1, 2)`的结构是逗号分隔的,包含两个元素的列表。因为模式代表一种值的结构,而不是特定的某个值,你可以把模式和各种同类型的值匹配起来。比如,`(x, y)`可以匹配元组`(1, 2)`,以及任何含两个元素的元组。除了将模式与一个值匹配外,你可以从合成值中提取出部分或全部,然后分别把各个部分和一个常量或变量绑定起来。 +模式(pattern)代表了单个值或者复合值的结构。例如,元组`(1, 2)`的结构是逗号分隔的,包含两个元素的列表。因为模式代表一种值的结构,而不是特定的某个值,你可以把模式和各种同类型的值匹配起来。比如,`(x, y)`可以匹配元组`(1, 2)`,以及任何含两个元素的元组。除了将模式与一个值匹配外,你可以从复合值中提取出部分或全部,然后分别把各个部分和一个常量或变量绑定起来。 -swift中有2个基本的模式种类:一类能成功和任何值的类型相匹配,另一类在运行时(runtime)和某特定值匹配时可能会失败。 +swift语言中模式有2个基本的分类:一类能成功和任何值的类型相匹配,另一类在运行时(runtime)和某特定值匹配时可能会失败。 -第一类模式用于解构简单变量,常量和可选绑定中的值。此类模式包括通配符模式(wildcard pattern),标识符模式(identifier pattern),以及任何包含了它们的值绑定模式(value binding pattern)或者元祖模式(tuple pattern)。你可以为这类模式指定一个类型注释(type annotation)来限制它们只能匹配某种特定类型的值。 +第一类模式用于解构简单变量,常量和可选绑定中的值。此类模式包括通配符模式(wildcard pattern),标识符模式(identifier pattern),以及任何包含了它们的值绑定模式(value binding pattern)或者元祖模式(tuple pattern)。你可以为这类模式指定一个类型注释(type annotation)从而限制它们只能匹配某种特定类型的值。 第二类模式用于全模式匹配,这种情况下你用来相比较的值在运行时可能还不存在。此类模式包括枚举用例模式,可选模式,表达式模式和类型转换模式。你在`switch`语句的case标签中,`do`语句的`catch`从句中,或者在`if, while, guard`和`for-in`语句的case条件句中使用这类模式。 @@ -28,9 +28,9 @@ swift中有2个基本的模式种类:一类能成功和任何值的类型相 > *模式* → [*标识符模式*](..\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#tuple_pattern) [*类型注解*](..\chapter3\03_Types.html#type_annotation) _可选_ -> *模式* → [*enum-case-pattern*](..\chapter3\07_Patterns.html#enum_case_pattern) +> *模式* → [*枚举用例模式*](..\chapter3\07_Patterns.html#enum_case_pattern) > *模式* → [*可选模式*](..\chapter3\07_Patterns.html#optional_pattern) [*类型注解*](..\chapter3\03_Types.html#optional_type) _可选_ -> *模式* → [*type-casting-pattern*](..\chapter3\07_Patterns.html#type_casting_pattern) +> *模式* → [*类型转换模式*](..\chapter3\07_Patterns.html#type_casting_pattern) > *模式* → [*表达式模式*](..\chapter3\07_Patterns.html#expression_pattern) @@ -75,7 +75,7 @@ let point = (3, 2) switch point { // Bind x and y to the elements of point. case let (x, y): -println("The point is at (\(x), \(y)).") +print("The point is at (\(x), \(y)).") } // prints "The point is at (3, 2).” ``` @@ -125,16 +125,12 @@ let (a): Int = 2 // a: Int = 2 > 枚举用例模式语法 > *enum-case-pattern* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) _可选_ **.** [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*元组模式*](..\chapter3\07_Patterns.html#tuple_pattern) _可选_ - - ## 可选模式(Optional Pattern) -可选模式 封装在一个`Some(T)` +可选模式与封装在一个`Optional(T)`或者一个`ExplicitlyUnwrappedOptional(T)`枚举中的`Some(T)`成员值相匹配。可选模式由一个标识符模式和紧随其后的一个问号组成,在某些情况下表现为枚举用例模式。 -可选模式由一个标识符模式和紧随其后的一个问号组成,在某种情况下表现为枚举用例模式。 - -由于可选模式是`optionan`和`ImplicitlyUnwrappedOptional`枚举用例模式的语法糖,下面的两种写法一样的: +由于可选模式是`optional`和`ImplicitlyUnwrappedOptional`枚举用例模式的语法糖(syntactic sugar),下面的两种写法一样的: ```swift let someOptional: Int? = 42 @@ -149,7 +145,7 @@ if case let x? = someOptional { } ``` -可选模式在`for-in`语句提供了在一个元素是可选类型的数组中迭代的简便的方式,只为数组中的非空元素执行循环。 +可选模式在`for-in`语句提供了在一个元素是可选类型的数组中迭代的简便方式,只为数组中的非空`non-nil`元素执行循环。 ```swift let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5] @@ -195,11 +191,11 @@ for case let number? in arrayOfOptinalInts { let point = (1, 2) switch point { case (0, 0): -println("(0, 0) is at the origin.") +print("(0, 0) is at the origin.") case (-2...2, -2...2): -println("(\(point.0), \(point.1)) is near the origin.") +print("(\(point.0), \(point.1)) is near the origin.") default: -println("The point is at (\(point.0), \(point.1)).") +print("The point is at (\(point.0), \(point.1)).") } // prints "(1, 2) is near the origin.” ``` @@ -213,11 +209,11 @@ return pattern == "\(value)" } switch point { case ("0", "0"): -println("(0, 0) is at the origin.") +print("(0, 0) is at the origin.") case ("-2...2", "-2...2"): -println("(\(point.0), \(point.1)) is near the origin.") +print("(\(point.0), \(point.1)) is near the origin.") default: -println("The point is at (\(point.0), \(point.1)).") +print("The point is at (\(point.0), \(point.1)).") } // prints "(1, 2) is near the origin.” ``` From 8f6eb4e2f6df46c44fdb69e7fe35716c395b5359 Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Mon, 29 Jun 2015 13:05:40 +0800 Subject: [PATCH 14/50] patterns_13:05_06/29/2015_Preliminary --- source/chapter3/07_Patterns.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 0795f26f..0b4f0bf5 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -1,4 +1,4 @@ -> 翻译:[honghaoz](https://github.com/honghaoz) +> 翻译:[honghaoz](https://github.com/honghaoz), [ray16897188](https://github.com/ray16897188) > 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai) # 模式(Patterns) @@ -144,8 +144,7 @@ if case let x? = someOptional { print(x) } ``` - -可选模式在`for-in`语句提供了在一个元素是可选类型的数组中迭代的简便方式,只为数组中的非空`non-nil`元素执行循环。 +如果一个数组的元素是可选类型,可选模式为`for-in`语句提供了在该数组中迭代的简便方式,只为数组中的非空`non-nil`元素执行循环。 ```swift let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5] From 84a31ca36b8a3679346d8f28a50078e6c24798b8 Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Mon, 29 Jun 2015 13:21:25 +0800 Subject: [PATCH 15/50] patterns_13:21_06/29/2015_Preliminary --- source/chapter3/07_Patterns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 0b4f0bf5..4e9e8660 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -158,7 +158,7 @@ for case let number? in arrayOfOptinalInts { ``` > 可选模式语法 -> *optional-pattern* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) ? +> *可选模式* → [*标识符模式*](..\chapter3\03_Types.html#type_identifier) ? ## 类型转换模式(Type-Casting Patterns) From 5946afca2ea7a1da97e5d390ee02e264a5b65826 Mon Sep 17 00:00:00 2001 From: futantan Date: Mon, 29 Jun 2015 11:27:13 +0800 Subject: [PATCH 16/50] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=A4=BA=E4=BE=8B?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8Cprintln()=20->=20println()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/08_Enumerations.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index 1484694f..570f1de2 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -79,13 +79,13 @@ directionToHead = .East directionToHead = .South switch directionToHead { case .North: - println("Lots of planets have a north") + print("Lots of planets have a north") case .South: - println("Watch out for penguins") + print("Watch out for penguins") case .East: - println("Where the sun rises") + print("Where the sun rises") case .West: - println("Where the skies are blue") + print("Where the skies are blue") } // 输出 "Watch out for penguins” ``` @@ -104,9 +104,9 @@ case .West: let somePlanet = Planet.Earth switch somePlanet { case .Earth: - println("Mostly harmless") + print("Mostly harmless") default: - println("Not a safe place for humans") + print("Not a safe place for humans") } // 输出 "Mostly harmless” ``` @@ -164,9 +164,9 @@ productBarcode = .QRCode("ABCDEFGHIJKLMNOP") ```swift switch productBarcode { case .UPCA(let numberSystem, let identifier, let check): - println("UPC-A with value of \(numberSystem), \(identifier), \(check).") + print("UPC-A with value of \(numberSystem), \(identifier), \(check).") case .QRCode(let productCode): - println("QR code with value of \(productCode).") + print("QR code with value of \(productCode).") } // 输出 "QR code with value of ABCDEFGHIJKLMNOP.” ``` @@ -176,9 +176,9 @@ case .QRCode(let productCode): ```swift switch productBarcode { case let .UPCA(numberSystem, identifier, check): - println("UPC-A with value of \(numberSystem), \(identifier), \(check).") + print("UPC-A with value of \(numberSystem), \(identifier), \(check).") case let .QRCode(productCode): - println("QR code with value of \(productCode).") + print("QR code with value of \(productCode).") } // 输出 "QR code with value of ABCDEFGHIJKLMNOP." ``` @@ -237,15 +237,14 @@ let positionToFind = 9 if let somePlanet = Planet(rawValue: positionToFind) { switch somePlanet { case .Earth: - println("Mostly harmless") + print("Mostly harmless") default: - println("Not a safe place for humans") + print("Not a safe place for humans") } } else { - println("There isn't a planet at position \(positionToFind)") + print("There isn't a planet at position \(positionToFind)") } // 输出 "There isn't a planet at position 9 ``` 这个范例使用可选绑定(optional binding),通过原始值`9`试图访问一个行星。`if let somePlanet = Planet(rawValue: 9)`语句获得一个可选`Planet`,如果可选`Planet`可以被获得,把`somePlanet`设置成该可选`Planet`的内容。在这个范例中,无法检索到位置为`9`的行星,所以`else`分支被执行。 - From 385123a16b04c630bb2fffd067ad6ecbe0379763 Mon Sep 17 00:00:00 2001 From: futantan Date: Mon, 29 Jun 2015 15:32:05 +0800 Subject: [PATCH 17/50] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=9E=9A=E4=B8=BE?= =?UTF-8?q?=EF=BC=8D=E6=A6=82=E8=BF=B0=E9=83=A8=E5=88=86=E6=A0=A1=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/08_Enumerations.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index 570f1de2..23c960a3 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -11,13 +11,13 @@ - [相关值(Associated Values)](#associated_values) - [原始值(Raw Values)](#raw_values) -枚举定义了一个通用类型的一组相关的值,使你可以在你的代码中以一个安全的方式来使用这些值。 +*枚举*定义了一个通用类型的一组相关值,使你可以在你的代码中以一种安全的方式来使用这些值。 -如果你熟悉 C 语言,你就会知道,在 C 语言中枚举指定相关名称为一组整型值。Swift 中的枚举更加灵活,不必给每一个枚举成员提供一个值。如果一个值(被认为是“原始”值)被提供给每个枚举成员,则该值可以是一个字符串,一个字符,或是一个整型值或浮点值。 +如果你熟悉 C 语言,你就会知道,在 C 语言中枚举将枚举名和一个整形值相对应。Swift 中的枚举更加灵活,不必给每一个枚举成员提供一个值。如果给枚举成员提供一个值(称为“原始”值),则该值的类型可以是字符串,字符,或是一个整型值或浮点数。 此外,枚举成员可以指定任何类型的相关值存储到枚举成员值中,就像其他语言中的联合体(unions)和变体(variants)。你可以定义一组通用的相关成员作为枚举的一部分,每一组都有不同的一组与它相关的适当类型的数值。 -在 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)。 From 13de9fc77b4b29e8729b46535d0e9c3c7119062b Mon Sep 17 00:00:00 2001 From: futantan Date: Mon, 29 Jun 2015 15:49:49 +0800 Subject: [PATCH 18/50] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=9E=9A=E4=B8=BE?= =?UTF-8?q?=E8=AF=AD=E6=B3=95=E6=A0=A1=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/08_Enumerations.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index 23c960a3..f5f74e3a 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -13,7 +13,7 @@ *枚举*定义了一个通用类型的一组相关值,使你可以在你的代码中以一种安全的方式来使用这些值。 -如果你熟悉 C 语言,你就会知道,在 C 语言中枚举将枚举名和一个整形值相对应。Swift 中的枚举更加灵活,不必给每一个枚举成员提供一个值。如果给枚举成员提供一个值(称为“原始”值),则该值的类型可以是字符串,字符,或是一个整型值或浮点数。 +如果你熟悉 C 语言,你就会知道,在 C 语言中枚举将枚举名和一个整型值相对应。Swift 中的枚举更加灵活,不必给每一个枚举成员提供一个值。如果给枚举成员提供一个值(称为“原始”值),则该值的类型可以是字符串,字符,或是一个整型值或浮点数。 此外,枚举成员可以指定任何类型的相关值存储到枚举成员值中,就像其他语言中的联合体(unions)和变体(variants)。你可以定义一组通用的相关成员作为枚举的一部分,每一组都有不同的一组与它相关的适当类型的数值。 @@ -24,7 +24,7 @@ ## 枚举语法 -使用`enum`关键词并且把它们的整个定义放在一对大括号内: +使用`enum`关键词来创建枚举并且把它们的整个定义放在一对大括号内: ```swift enum SomeEnumeration { @@ -46,7 +46,7 @@ enum CompassPoint { 一个枚举中被定义的值(例如 `North`,`South`,`East`和`West`)是枚举的***成员值***(或者***成员***)。`case`关键词表明新的一行成员值将被定义。 > 注意: -> 不像 C 和 Objective-C 一样,Swift 的枚举成员在被创建时不会被赋予一个默认的整数值。在上面的`CompassPoints`例子中,`North`,`South`,`East`和`West`不是隐式的等于`0`,`1`,`2`和`3`。相反的,这些不同的枚举成员在`CompassPoint`的一种显示定义中拥有各自不同的值。 +> 和 C 和 Objective-C 不同,Swift 的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的`CompassPoints`例子中,`North`,`South`,`East`和`West`不会隐式地赋值为了`0`,`1`,`2`和`3`。相反的,这些不同的枚举成员在`CompassPoint`的一种显示定义中拥有各自不同的值。 多个成员值可以出现在同一行上,用逗号隔开: @@ -62,13 +62,13 @@ enum Planet { var directionToHead = CompassPoint.West ``` -`directionToHead`的类型被推断当它被`CompassPoint`的一个可能值初始化。一旦`directionToHead`被声明为一个`CompassPoint`,你可以使用更短的点(.)语法将其设置为另一个`CompassPoint`的值: +`directionToHead`的类型可以在它被`CompassPoint`的一个可能值初始化时推断出来。一旦`directionToHead`被声明为一个`CompassPoint`,你可以使用一个缩写语法(.)将其设置为另一个`CompassPoint`的值: ```swift directionToHead = .East ``` -`directionToHead`的类型已知时,当设定它的值时,你可以不再写类型名。使用显式类型的枚举值可以让代码具有更好的可读性。 +当`directionToHead`的类型已知时,再次为其赋值可以省略枚举名。使用显式类型的枚举值可以让代码具有更好的可读性。 ## 匹配枚举值和`Switch`语句 From 42b2f0d17bfb8efc8c49a9f8e56c6c72dcf4bbd6 Mon Sep 17 00:00:00 2001 From: futantan Date: Mon, 29 Jun 2015 16:01:04 +0800 Subject: [PATCH 19/50] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=9E=9A=E4=B8=BE-?= =?UTF-8?q?=E5=8C=B9=E9=85=8D=E6=9E=9A=E4=B8=BE=E5=80=BC=E5=92=8CSwitch?= =?UTF-8?q?=E8=AF=AD=E5=8F=A5=E6=A0=A1=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/08_Enumerations.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index f5f74e3a..7c8f60d5 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -73,7 +73,7 @@ directionToHead = .East ## 匹配枚举值和`Switch`语句 -你可以匹配单个枚举值和`switch`语句: +你可以使用`switch`语句匹配单个枚举值: ```swift directionToHead = .South @@ -90,15 +90,15 @@ case .West: // 输出 "Watch out for penguins” ``` -你可以如此理解这段代码: +你可以这样理解这段代码: -“考虑`directionToHead`的值。当它等于`.North`,打印`“Lots of planets have a north”`。当它等于`.South`,打印`“Watch out for penguins”`。” +“判断`directionToHead`的值。当它等于`.North`,打印`“Lots of planets have a north”`。当它等于`.South`,打印`“Watch out for penguins”`。” -等等依次类推。 +等等以此类推。 -正如在[控制流(Control Flow)](05_Control_Flow.html)中介绍,当考虑一个枚举的成员们时,一个`switch`语句必须全面。如果忽略了`.West`这种情况,上面那段代码将无法通过编译,因为它没有考虑到`CompassPoint`的全部成员。全面性的要求确保了枚举成员不会被意外遗漏。 +正如在[控制流(Control Flow)](05_Control_Flow.html)中介绍的那样,在判断一个枚举类型的值时,`switch`语句必须穷举所有情况。如果忽略了`.West`这种情况,上面那段代码将无法通过编译,因为它没有考虑到`CompassPoint`的全部成员。强制性全部穷举的要求确保了枚举成员不会被意外遗漏。 -当不需要匹配每个枚举成员的时候,你可以提供一个默认`default`分支来涵盖所有未明确被提出的任何成员: +当不需要匹配每个枚举成员的时候,你可以提供一个默认`default`分支来涵盖所有未明确被提出的枚举成员: ```swift let somePlanet = Planet.Earth From 13ef8f1bd68840a46fb63ea0188817be10899fa6 Mon Sep 17 00:00:00 2001 From: futantan Date: Mon, 29 Jun 2015 16:28:11 +0800 Subject: [PATCH 20/50] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=9E=9A=E4=B8=BE-?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=80=BC=EF=BC=88Associated=20Values?= =?UTF-8?q?=EF=BC=89=E6=A0=A1=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/08_Enumerations.md | 34 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index 7c8f60d5..a9f72ce4 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -43,7 +43,7 @@ enum CompassPoint { } ``` -一个枚举中被定义的值(例如 `North`,`South`,`East`和`West`)是枚举的***成员值***(或者***成员***)。`case`关键词表明新的一行成员值将被定义。 +一个枚举中被定义的值(例如 `North`,`South`,`East`和`West`)是枚举的*成员值*(或者*成员*)。`case`关键词表明新的一行成员值将被定义。 > 注意: > 和 C 和 Objective-C 不同,Swift 的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的`CompassPoints`例子中,`North`,`South`,`East`和`West`不会隐式地赋值为了`0`,`1`,`2`和`3`。相反的,这些不同的枚举成员在`CompassPoint`的一种显示定义中拥有各自不同的值。 @@ -114,11 +114,11 @@ default: ## 相关值(Associated Values) -上一小节的例子演示了一个枚举的成员是如何被定义(分类)的。你可以为`Planet.Earth`设置一个常量或则变量,并且在之后查看这个值。不管怎样,如果有时候能够把其他类型的相关值和成员值一起存储起来会很有用。这能让你存储成员值之外的自定义信息,并且当你每次在代码中使用该成员时允许这个信息产生变化。 +上一小节的例子演示了如何定义(分类)枚举的成员。你可以为`Planet.Earth`设置一个常量或者变量,并且在赋值之后查看这个值。不管怎样,如果有时候能够把其他类型的*相关值*和成员值一起存储起来会很有用。这能让你存储成员值之外的自定义信息,并且当你每次在代码中使用该成员时允许这个信息产生变化。 你可以定义 Swift 的枚举存储任何类型的相关值,如果需要的话,每个成员的数据类型可以是各不相同的。枚举的这种特性跟其他语言中的可辨识联合(discriminated unions),标签联合(tagged unions),或者变体(variants)相似。 -例如,假设一个库存跟踪系统需要利用两种不同类型的条形码来跟踪商品。有些商品上标有 UPC-A 格式的一维码,它使用数字 0 到 9。每一个条形码都有一个代表“数字系统”的数字,该数字后接 10 个代表“标识符”的数字。最后一个数字是“检查”位,用来验证代码是否被正确扫描: +例如,假设一个库存跟踪系统需要利用两种不同类型的条形码来跟踪商品。有些商品上标有 UPC-A 格式的一维t条形码,它使用数字 0 到 9。每一个条形码都有一个代表“数字系统”的数字,该数字后接 5 个代表“生产代码”的数字,接下来是5位“产品代码”。最后一个数字是“检查”位,用来验证代码是否被正确扫描: @@ -128,28 +128,28 @@ default: 对于库存跟踪系统来说,能够把 UPC-A 码作为三个整型值的元组,和把 QR 码作为一个任何长度的字符串存储起来是方便的。 -在 Swift 中,用来定义两种商品条码的枚举是这样子的: +在 Swift 中,使用如下方式定义两种商品条码的枚举: ```swift enum Barcode { - case UPCA(Int, Int, Int) + case UPCA(Int, Int, Int, Int) case QRCode(String) } ``` 以上代码可以这么理解: -“定义一个名为`Barcode`的枚举类型,它可以是`UPCA`的一个相关值(`Int`,`Int`,`Int`),或者`QRCode`的一个字符串类型(`String`)相关值。” +“定义一个名为`Barcode`的枚举类型,它可以是`UPCA`的一个相关值(`Int`,`Int`,`Int`,`Int`),或者是`QRCode`的一个字符串类型(`String`)相关值。” 这个定义不提供任何`Int`或`String`的实际值,它只是定义了,当`Barcode`常量和变量等于`Barcode.UPCA`或`Barcode.QRCode`时,相关值的类型。 然后可以使用任何一种条码类型创建新的条码,如: ```swift -var productBarcode = Barcode.UPCA(8, 85909_51226, 3) +var productBarcode = Barcode.UPCA(8, 85909, 51226, 3) ``` -以上例子创建了一个名为`productBarcode`的新变量,并且赋给它一个`Barcode.UPCA`的相关元组值`(8, 8590951226, 3)`。提供的“标识符”值在整数字中有一个下划线,使其便于阅读条形码。 +以上例子创建了一个名为`productBarcode`的变量,并且赋给它一个`Barcode.UPCA`的相关元组值`(8, 85909, 51226, 3)`。 同一个商品可以被分配给一个不同类型的条形码,如: @@ -163,24 +163,24 @@ productBarcode = .QRCode("ABCDEFGHIJKLMNOP") ```swift switch productBarcode { -case .UPCA(let numberSystem, let identifier, let check): - print("UPC-A with value of \(numberSystem), \(identifier), \(check).") +case .UPCA(let numberSystem, let manufacturer, let product, let check): + print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).") case .QRCode(let productCode): - print("QR code with value of \(productCode).") + print("QR code: \(productCode).") } -// 输出 "QR code with value of ABCDEFGHIJKLMNOP.” +// 输出 "QR code: ABCDEFGHIJKLMNOP." ``` 如果一个枚举成员的所有相关值被提取为常量,或者它们全部被提取为变量,为了简洁,你可以只放置一个`var`或者`let`标注在成员名称前: ```swift switch productBarcode { -case let .UPCA(numberSystem, identifier, check): - print("UPC-A with value of \(numberSystem), \(identifier), \(check).") +case let .UPCA(numberSystem, manufacturer, product, check): + print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).") case let .QRCode(productCode): - print("QR code with value of \(productCode).") + print("QR code: \(productCode).") } -// 输出 "QR code with value of ABCDEFGHIJKLMNOP." +// 输出 "QR code: ABCDEFGHIJKLMNOP." ``` @@ -228,7 +228,7 @@ let possiblePlanet = Planet(rawValue: 7) // possiblePlanet is of type Planet? and equals Planet.Uranus ``` -然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个***可选***的枚举成员。在上面的例子中,`possiblePlanet`是`Planet?`类型,或“可选的`Planet`”。 +然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个*可选*的枚举成员。在上面的例子中,`possiblePlanet`是`Planet?`类型,或“可选的`Planet`”。 如果你试图寻找一个位置为9的行星,通过参数为`rawValue`构造函数返回的可选`Planet`值将是`nil`: From cb01035cd29a9dc3d3c7089def576d28e086d9e7 Mon Sep 17 00:00:00 2001 From: futantan Date: Mon, 29 Jun 2015 17:23:03 +0800 Subject: [PATCH 21/50] =?UTF-8?q?=E5=AE=8C=E6=88=90=20=E6=9E=9A=E4=B8=BE-?= =?UTF-8?q?=E5=8E=9F=E5=A7=8B=E5=80=BC(Raw=20Values)=E6=A0=A1=E5=AF=B9=20?= =?UTF-8?q?=E5=90=AB=E6=9C=89=E4=B8=80=E4=B8=AAtodo=20=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=9E=9A=E4=B8=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/08_Enumerations.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index a9f72ce4..0ba75399 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -19,7 +19,7 @@ 在 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)。 ## 枚举语法 @@ -186,9 +186,9 @@ case let .QRCode(productCode): ## 原始值(Raw Values) -在[Associated Values](#raw_values)小节的条形码例子中演示了一个枚举的成员如何声明它们存储不同类型的相关值。作为相关值的替代,枚举成员可以被默认值(称为原始值)预先填充,其中这些原始值具有相同的类型。 +在[Associated Values](#raw_values)小节的条形码例子中演示了一个枚举的成员如何声明它们存储不同类型的相关值。作为相关值的另一种选择,枚举成员可以被默认值(称为原始值)赋值,其中这些原始值具有相同的类型。 -这里是一个枚举成员存储原始 ASCII 值的例子: +这里是一个枚举成员存储 ASCII 码的例子: ```swift enum ASCIIControlCharacter: Character { @@ -198,11 +198,11 @@ enum ASCIIControlCharacter: Character { } ``` -在这里,称为`ASCIIControlCharacter`的枚举的原始值类型被定义为字符型`Character`,并被设置了一些比较常见的 ASCII 控制字符。字符值的描述请详见字符串和字符[`Strings and Characters`](03_Strings_and_Characters.html)部分。 +在这里,`ASCIIControlCharacter`的枚举类型的原始值类型被定义为字符型`Character`,并被设置了一些比较常见的 ASCII 控制字符。字符值的描述请详见字符串和字符[`Strings and Characters`](03_Strings_and_Characters.html)部分。 -注意,原始值和相关值是不相同的。当你开始在你的代码中定义枚举的时候原始值是被预先填充的值,像上述三个 ASCII 码。对于一个特定的枚举成员,它的原始值始终是相同的。相关值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。 +注意,原始值和相关值是不相同的。原始值是当你开始定义枚举的时候被预先赋予的值,像上述三个 ASCII 码。对于一个特定的枚举成员,它的原始值始终是相同的。相关值在你在创建一个基于枚举成员的常量或变量时才会被设置,并且每次当你创建的时候,它的值可以是不同的。 -原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。当整型值被用于原始值,如果其他枚举成员没有值时,它们会自动递增。 +原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。当使用整型值作为原始值时,如果其他枚举成员没有值,它们会自动递增。 下面的枚举是对之前`Planet`这个枚举的一个细化,利用原始整型值来表示每个 planet 在太阳系中的顺序: @@ -212,7 +212,7 @@ enum Planet: Int { } ``` -自动递增意味着`Planet.Venus`的原始值是`2`,依次类推。 +自动递增意味着`Planet.Venus`的原始值是`2`,以此类推。 使用枚举成员的`rawValue`属性可以访问该枚举成员的原始值: @@ -220,15 +220,22 @@ enum Planet: Int { let earthsOrder = Planet.Earth.rawValue // earthsOrder is 3 ``` +### 使用原始值来初始化(Initializing from a Raw Value) -通过参数为`rawValue`构造函数创建特定原始值的枚举。这个例子通过原始值`7`识别`Uranus`: +如果你使用原始值的方式创建一个枚举类型,这个枚举将自动获得一个包含原始值参数(参数名为rawValue)的构造器并返回相应的枚举类型或者nil。你可以使用这个构造器来创建新的枚举成员。 + +下面这个例子通过原始值`7`创建了`Uranus`枚举类型: ```swift let possiblePlanet = Planet(rawValue: 7) // possiblePlanet is of type Planet? and equals Planet.Uranus ``` -然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个*可选*的枚举成员。在上面的例子中,`possiblePlanet`是`Planet?`类型,或“可选的`Planet`”。 +然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个*可选*的枚举成员。在上面的例子中,`possiblePlanet`是`Planet?`类型,或称为“可选的`Planet`”。 + +> 注意: +> 使用原始值构造器是可失败构造器,因为并不是所有的原始值都会返回一个对应的枚举成员。欲了解更多相关信息,请参见[可失败构造器(Failable Initializers)](留空) + 如果你试图寻找一个位置为9的行星,通过参数为`rawValue`构造函数返回的可选`Planet`值将是`nil`: @@ -247,4 +254,4 @@ if let somePlanet = Planet(rawValue: positionToFind) { // 输出 "There isn't a planet at position 9 ``` -这个范例使用可选绑定(optional binding),通过原始值`9`试图访问一个行星。`if let somePlanet = Planet(rawValue: 9)`语句获得一个可选`Planet`,如果可选`Planet`可以被获得,把`somePlanet`设置成该可选`Planet`的内容。在这个范例中,无法检索到位置为`9`的行星,所以`else`分支被执行。 +这个范例使用可选绑定(optional binding),通过原始值`9`试图取得一个行星的引用。`if let somePlanet = Planet(rawValue: 9)`语句获得一个可选`Planet`,如果可选`Planet`可以被获得,把`somePlanet`设置成该可选`Planet`的内容。在这个范例中,无法检索到位置为`9`的行星,所以`else`分支被执行。 From 27f3736b2538b045f6be7667f51960531a1c91c4 Mon Sep 17 00:00:00 2001 From: futantan Date: Mon, 29 Jun 2015 18:25:08 +0800 Subject: [PATCH 22/50] =?UTF-8?q?=E4=BF=AE=E6=94=B9todo=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/08_Enumerations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/chapter2/08_Enumerations.md b/source/chapter2/08_Enumerations.md index 0ba75399..c0d7c949 100755 --- a/source/chapter2/08_Enumerations.md +++ b/source/chapter2/08_Enumerations.md @@ -234,8 +234,8 @@ let possiblePlanet = Planet(rawValue: 7) 然而,并非所有可能的`Int`值都可以找到一个匹配的行星。正因为如此,构造函数可以返回一个*可选*的枚举成员。在上面的例子中,`possiblePlanet`是`Planet?`类型,或称为“可选的`Planet`”。 > 注意: -> 使用原始值构造器是可失败构造器,因为并不是所有的原始值都会返回一个对应的枚举成员。欲了解更多相关信息,请参见[可失败构造器(Failable Initializers)](留空) - +> 使用原始值构造器是可失败构造器,因为并不是所有的原始值都会返回一个对应的枚举成员。欲了解更多相关信息,请参见[可失败构造器(Failable Initializers)](TODO) + 如果你试图寻找一个位置为9的行星,通过参数为`rawValue`构造函数返回的可选`Planet`值将是`nil`: From 74cff1433f7989959cc8b1421ac8fb26812d77a4 Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Mon, 29 Jun 2015 19:38:02 +0800 Subject: [PATCH 23/50] patterns_19:37_06/29/2015 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改了print函数的缩进格式 --- source/chapter3/07_Patterns.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 4e9e8660..6fd48bf8 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -75,7 +75,7 @@ let point = (3, 2) switch point { // Bind x and y to the elements of point. case let (x, y): -print("The point is at (\(x), \(y)).") + print("The point is at (\(x), \(y)).") } // prints "The point is at (3, 2).” ``` @@ -190,11 +190,11 @@ for case let number? in arrayOfOptinalInts { let point = (1, 2) switch point { case (0, 0): -print("(0, 0) is at the origin.") + print("(0, 0) is at the origin.") case (-2...2, -2...2): -print("(\(point.0), \(point.1)) is near the origin.") + print("(\(point.0), \(point.1)) is near the origin.") default: -print("The point is at (\(point.0), \(point.1)).") + print("The point is at (\(point.0), \(point.1)).") } // prints "(1, 2) is near the origin.” ``` @@ -208,11 +208,11 @@ return pattern == "\(value)" } switch point { case ("0", "0"): -print("(0, 0) is at the origin.") + print("(0, 0) is at the origin.") case ("-2...2", "-2...2"): -print("(\(point.0), \(point.1)) is near the origin.") + print("(\(point.0), \(point.1)) is near the origin.") default: -print("The point is at (\(point.0), \(point.1)).") + print("The point is at (\(point.0), \(point.1)).") } // prints "(1, 2) is near the origin.” ``` From edca3127080b9109087d11a83440c90eb43a03f2 Mon Sep 17 00:00:00 2001 From: justaway Date: Mon, 29 Jun 2015 20:23:03 +0800 Subject: [PATCH 24/50] =?UTF-8?q?=E5=AE=8C=E6=88=90'=E8=AF=8D=E6=B3=95?= =?UTF-8?q?=E7=BB=93=E6=9E=84'=E7=9A=84=E6=A0=A1=E5=AF=B9=E5=92=8C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter3/02_Lexical_Structure.md | 517 +++++++++++++----------- 1 file changed, 279 insertions(+), 238 deletions(-) diff --git a/source/chapter3/02_Lexical_Structure.md b/source/chapter3/02_Lexical_Structure.md index ca1ac6a9..0fd074a2 100755 --- a/source/chapter3/02_Lexical_Structure.md +++ b/source/chapter3/02_Lexical_Structure.md @@ -1,238 +1,279 @@ -> 翻译:[superkam](https://github.com/superkam) -> 校对:[numbbbbb](https://github.com/numbbbbb) - -# 词法结构 ------------------ - -本页包含内容: - -- [空白与注释(*Whitespace and Comments*)](#whitespace_and_comments) -- [标识符(*Identifiers*)](#identifiers) -- [关键字(*Keywords*)](#keywords) -- [字面量(*Literals*)](#literals) -- [运算符(*Operators*)](#operators) - -Swift 的“词法结构(*lexical structure*)”描述了如何在该语言中用字符序列构建合法标记,组成该语言中最底层的代码块,并在之后的章节中用于描述语言的其他部分。 - -通常,标记在随后介绍的语法约束下,由 Swift 源文件的输入文本中提取可能的最长子串生成。这种方法称为“最长匹配项(*longest match*)”,或者“最大适合”(*maximal munch*)。 - - -## 空白与注释 - -空白(*whitespace*)有两个用途:分隔源文件中的标记和区分运算符属于前缀还是后缀,(参见 [运算符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_871))在其他情况下则会被忽略。以下的字符会被当作空白:空格(*space*)(U+0020)、换行符(*line feed*)(U+000A)、回车符(*carriage return*)(U+000D)、水平 tab(*horizontal tab*)(U+0009)、垂直 tab(*vertical tab*)(U+000B)、换页符(*form feed*)(U+000C)以及空(*null*)(U+0000)。 - -注释(*comments*)被编译器当作空白处理。单行注释由 `//` 开始直到该行结束。多行注释由 `/*` 开始,以 `*/` 结束。可以嵌套注释,但注意注释标记必须匹配。 - - -## 标识符 - -标识符(*identifiers*)可以由以下的字符开始:大写或小写的字母 `A` 到 `Z`、下划线 `_`、基本多语言面(*Basic Multilingual Plane*)中的 Unicode 非组合字符以及基本多语言面以外的非专用区(*Private Use Area*)字符。首字符之后,标识符允许使用数字和 Unicode 字符组合。 - -使用保留字(*reserved word*)作为标识符,需要在其前后增加反引号 \`。例如,class 不是合法的标识符,但可以使用 \`class\`。反引号不属于标识符的一部分,\`x\` 和 `x` 表示同一标识符。 - -闭包(*closure*)中如果没有明确指定参数名称,参数将被隐式命名为 $0$1$2... 这些命名在闭包作用域内是合法的标识符。 - -> 标识符语法 -> *标识符* → [*标识符头(Head)*](LexicalStructure.html#identifier_head) [*标识符字符列表*](LexicalStructure.html#identifier_characters) _可选_ -> *标识符* → **`** [*标识符头(Head)*](LexicalStructure.html#identifier_head) [*标识符字符列表*](LexicalStructure.html#identifier_characters) _可选_ **`** -> *标识符* → [*隐式参数名*](LexicalStructure.html#implicit_parameter_name) -> *标识符列表* → [*标识符*](LexicalStructure.html#identifier) | [*标识符*](LexicalStructure.html#identifier) **,** [*标识符列表*](LexicalStructure.html#identifier_list) -> *标识符头(Head)* → Upper- or lowercase letter A through Z -> *标识符头(Head)* → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2–U+00B5, or U+00B7–U+00BA -> *标识符头(Head)* → U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, or U+00F8–U+00FF -> *标识符头(Head)* → U+0100–U+02FF, U+0370–U+167F, U+1681–U+180D, or U+180F–U+1DBF -> *标识符头(Head)* → U+1E00–U+1FFF -> *标识符头(Head)* → U+200B–U+200D, U+202A–U+202E, U+203F–U+2040, U+2054, or U+2060–U+206F -> *标识符头(Head)* → U+2070–U+20CF, U+2100–U+218F, U+2460–U+24FF, or U+2776–U+2793 -> *标识符头(Head)* → U+2C00–U+2DFF or U+2E80–U+2FFF -> *标识符头(Head)* → U+3004–U+3007, U+3021–U+302F, U+3031–U+303F, or U+3040–U+D7FF -> *标识符头(Head)* → U+F900–U+FD3D, U+FD40–U+FDCF, U+FDF0–U+FE1F, or U+FE30–U+FE44 -> *标识符头(Head)* → U+FE47–U+FFFD -> *标识符头(Head)* → U+10000–U+1FFFD, U+20000–U+2FFFD, U+30000–U+3FFFD, or U+40000–U+4FFFD -> *标识符头(Head)* → U+50000–U+5FFFD, U+60000–U+6FFFD, U+70000–U+7FFFD, or U+80000–U+8FFFD -> *标识符头(Head)* → U+90000–U+9FFFD, U+A0000–U+AFFFD, U+B0000–U+BFFFD, or U+C0000–U+CFFFD -> *标识符头(Head)* → U+D0000–U+DFFFD or U+E0000–U+EFFFD -> *标识符字符* → 数值 0 到 9 -> *标识符字符* → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+FE2F -> *标识符字符* → [*标识符头(Head)*](LexicalStructure.html#identifier_head) -> *标识符字符列表* → [*标识符字符*](LexicalStructure.html#identifier_character) [*标识符字符列表*](LexicalStructure.html#identifier_characters) _可选_ -> *隐式参数名* → **$** [*十进制数字列表*](LexicalStructure.html#decimal_digits) - - -## 关键字 - -被保留的关键字(*keywords*)不允许用作标识符,除非被反引号转义,参见 [标识符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_796)。 - -* **用作声明的关键字:** *class*、*deinit*、*enum*、*extension*、*func*、*import*、*init*、*let*、*protocol*、*static*、*struct*、*subscript*、*typealias*、*var* -* **用作语句的关键字:** *break*、*case*、*continue*、*default*、*do*、*else*、*fallthrough*、*if*、*in*、*for*、*return*、*switch*、*where*、*while* -* **用作表达和类型的关键字:** *as*、*dynamicType*、*is*、*new*、*super*、*self*、*Self*、*Type*、*\_\_COLUMN\_\_*、*\_\_FILE\_\_*、*\_\_FUNCTION\_\_*、*\_\_LINE\_\_* -* **特定上下文中被保留的关键字:** *associativity*、*didSet*、*get*、*infix*、*inout*、*left*、*mutating*、*none*、*nonmutating*、*operator*、*override*、*postfix*、 - *precedence*、*prefix*、*right*、*set*、*unowned*、*unowned(safe)*、*unowned(unsafe)*、*weak*、*willSet*,这些关键字在特定上下文之外可以被用于标识符。 - - -## 字面量 - -字面值表示整型、浮点型数字或文本类型的值,举例如下: - -```swift -42 // 整型字面量 -3.14159 // 浮点型字面量 -"Hello, world!" // 文本型字面量 -``` - -> 字面量语法 -> *字面量* → [*整型字面量*](LexicalStructure.html#integer_literal) | [*浮点数字面量*](LexicalStructure.html#floating_point_literal) | [*字符串字面量*](LexicalStructure.html#string_literal) - -### 整型字面量 - -整型字面量(*integer literals*)表示未指定精度整型数的值。整型字面量默认用十进制表示,可以加前缀来指定其他的进制,二进制字面量加 `0b`,八进制字面量加 `0o`,十六进制字面量加 `0x`。 - -十进制字面量包含数字 `0` 至 `9`。二进制字面量只包含 `0` 或 `1`,八进制字面量包含数字 `0` 至 `7`,十六进制字面量包含数字 `0` 至 `9` 以及字母 `A` 至 `F` (大小写均可)。 - -负整数的字面量在数字前加减号 `-`,比如 `-42`。 - -允许使用下划线 `_` 来增加数字的可读性,下划线不会影响字面量的值。整型字面量也可以在数字前加 `0`,同样不会影响字面量的值。 - -```swift -1000_000 // 等于 1000000 -005 // 等于 5 -``` - -除非特殊指定,整型字面量的默认类型为 Swift 标准库类型中的 `Int`。Swift 标准库还定义了其他不同长度以及是否带符号的整数类型,请参考 [整数类型](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_411)。 - -> 整型字面量语法 -> *整型字面量* → [*二进制字面量*](LexicalStructure.html#binary_literal) -> *整型字面量* → [*八进制字面量*](LexicalStructure.html#octal_literal) -> *整型字面量* → [*十进制字面量*](LexicalStructure.html#decimal_literal) -> *整型字面量* → [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) -> *二进制字面量* → **0b** [*二进制数字*](LexicalStructure.html#binary_digit) [*二进制字面量字符列表*](LexicalStructure.html#binary_literal_characters) _可选_ -> *二进制数字* → 数值 0 到 1 -> *二进制字面量字符* → [*二进制数字*](LexicalStructure.html#binary_digit) | **_** -> *二进制字面量字符列表* → [*二进制字面量字符*](LexicalStructure.html#binary_literal_character) [*二进制字面量字符列表*](LexicalStructure.html#binary_literal_characters) _可选_ -> *八进制字面量* → **0o** [*八进字数字*](LexicalStructure.html#octal_digit) [*八进制字符列表*](LexicalStructure.html#octal_literal_characters) _可选_ -> *八进字数字* → 数值 0 到 7 -> *八进制字符* → [*八进字数字*](LexicalStructure.html#octal_digit) | **_** -> *八进制字符列表* → [*八进制字符*](LexicalStructure.html#octal_literal_character) [*八进制字符列表*](LexicalStructure.html#octal_literal_characters) _可选_ -> *十进制字面量* → [*十进制数字*](LexicalStructure.html#decimal_digit) [*十进制字符列表*](LexicalStructure.html#decimal_literal_characters) _可选_ -> *十进制数字* → 数值 0 到 9 -> *十进制数字列表* → [*十进制数字*](LexicalStructure.html#decimal_digit) [*十进制数字列表*](LexicalStructure.html#decimal_digits) _可选_ -> *十进制字符* → [*十进制数字*](LexicalStructure.html#decimal_digit) | **_** -> *十进制字符列表* → [*十进制字符*](LexicalStructure.html#decimal_literal_character) [*十进制字符列表*](LexicalStructure.html#decimal_literal_characters) _可选_ -> *十六进制字面量* → **0x** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制字面量字符列表*](LexicalStructure.html#hexadecimal_literal_characters) _可选_ -> *十六进制数字* → 数值 0 到 9, a through f, or A through F -> *十六进制字符* → [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) | **_** -> *十六进制字面量字符列表* → [*十六进制字符*](LexicalStructure.html#hexadecimal_literal_character) [*十六进制字面量字符列表*](LexicalStructure.html#hexadecimal_literal_characters) _可选_ - -### 浮点型字面量 - -浮点型字面量(*floating-point literals*)表示未指定精度浮点数的值。 - -浮点型字面量默认用十进制表示(无前缀),也可以用十六进制表示(加前缀 `0x`)。 - -十进制浮点型字面量(*decimal floating-point literals*)由十进制数字串后跟小数部分或指数部分(或两者皆有)组成。十进制小数部分由小数点 `.` 后跟十进制数字串组成。指数部分由大写或小写字母 `e` 后跟十进制数字串组成,这串数字表示 `e` 之前的数量乘以 10 的几次方。例如:`1.25e2` 表示 `1.25 ⨉ 10^2`,也就是 `125.0`;同样,`1.25e-2` 表示 `1.25 ⨉ 10^-2`,也就是 `0.0125`。 - -十六进制浮点型字面量(*hexadecimal floating-point literals*)由前缀 `0x` 后跟可选的十六进制小数部分以及十六进制指数部分组成。十六进制小数部分由小数点后跟十六进制数字串组成。指数部分由大写或小写字母 `p` 后跟十进制数字串组成,这串数字表示 `p` 之前的数量乘以 2 的几次方。例如:`0xFp2` 表示 `15 ⨉ 2^2`,也就是 `60`;同样,`0xFp-2` 表示 `15 ⨉ 2^-2`,也就是 `3.75`。 - -与整型字面量不同,负的浮点型字面量由一元运算符减号 `-` 和浮点型字面量组成,例如 `-42.0`。这代表一个表达式,而不是一个浮点整型字面量。 - -允许使用下划线 `_` 来增强可读性,下划线不会影响字面量的值。浮点型字面量也可以在数字前加 `0`,同样不会影响字面量的值。 - -```swift -10_000.56 // 等于 10000.56 -005000.76 // 等于 5000.76 -``` - -除非特殊指定,浮点型字面量的默认类型为 Swift 标准库类型中的 `Double`,表示64位浮点数。Swift 标准库也定义 `Float` 类型,表示32位浮点数。 - -> 浮点型字面量语法 -> *浮点数字面量* → [*十进制字面量*](LexicalStructure.html#decimal_literal) [*十进制分数*](LexicalStructure.html#decimal_fraction) _可选_ [*十进制指数*](LexicalStructure.html#decimal_exponent) _可选_ -> *浮点数字面量* → [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) [*十六进制分数*](LexicalStructure.html#hexadecimal_fraction) _可选_ [*十六进制指数*](LexicalStructure.html#hexadecimal_exponent) -> *十进制分数* → **.** [*十进制字面量*](LexicalStructure.html#decimal_literal) -> *十进制指数* → [*浮点数e*](LexicalStructure.html#floating_point_e) [*正负号*](LexicalStructure.html#sign) _可选_ [*十进制字面量*](LexicalStructure.html#decimal_literal) -> *十六进制分数* → **.** [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) _可选_ -> *十六进制指数* → [*浮点数p*](LexicalStructure.html#floating_point_p) [*正负号*](LexicalStructure.html#sign) _可选_ [*十六进制字面量*](LexicalStructure.html#hexadecimal_literal) -> *浮点数e* → **e** | **E** -> *浮点数p* → **p** | **P** -> *正负号* → **+** | **-** - -### 文本型字面量 - -文本型字面量(*string literal*)由双引号中的字符串组成,形式如下: - -```swift -"characters" -``` - -文本型字面量中不能包含未转义的双引号 `"`、未转义的反斜线`\`、回车符(*carriage return*)或换行符(*line feed*)。 - -可以在文本型字面量中使用的转义特殊符号如下: - -* 空字符(Null Character)`\0` -* 反斜线(Backslash)`\\` -* 水平 Tab (Horizontal Tab)`\t` -* 换行符(Line Feed)`\n` -* 回车符(Carriage Return)`\r` -* 双引号(Double Quote)`\"` -* 单引号(Single Quote)`\'` - -字符也可以用以下方式表示: - -* `\x` 后跟两位十六进制数字 -* `\u` 后跟四位十六进制数字 -* `\U` 后跟八位十六进制数字 - -后跟的数字表示一个 Unicode 码点。 - -文本型字面量允许在反斜线小括号 `\()` 中插入表达式的值。插入表达式(*interpolated expression*)不能包含未转义的双引号 `"`、反斜线 `\`、回车符或者换行符。表达式值的类型必须在 *String* 类中有对应的初始化方法。 - -例如,以下所有文本型字面量的值相同: - -```swift -"1 2 3" -"1 2 \(3)" -"1 2 \(1 + 2)" -var 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)。 - -> 字符型字面量语法 -> *字符串字面量* → **"** [*引用文本*](LexicalStructure.html#quoted_text) **"** -> *引用文本* → [*引用文本条目*](LexicalStructure.html#quoted_text_item) [*引用文本*](LexicalStructure.html#quoted_text) _可选_ -> *引用文本条目* → [*转义字符*](LexicalStructure.html#escaped_character) -> *引用文本条目* → **\(** [*表达式*](..\chapter3\04_Expressions.html#expression) **)** -> *引用文本条目* → 除了"­, \­, U+000A, or U+000D的所有Unicode的字符 -> *转义字符* → **\0** | **\\** | **\t** | **\n** | **\r** | **\"** | **\'** -> *转义字符* → **\x** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) -> *转义字符* → **\u** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) -> *转义字符* → **\U** [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) [*十六进制数字*](LexicalStructure.html#hexadecimal_digit) - - -## 运算符 - -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) 中进行了阐述。这里将描述哪些字符能用作运算符。 - -运算符由一个或多个以下字符组成: -`/`、`=`、`-`、`+`、`!`、`*`、`%`、`<`、`>`、`&`、`|`、`^`、`~`、`.`。也就是说,标记 `=`, `->`、`//`、`/*`、`*/`、`.` 以及一元前缀运算符 `&` 属于保留字,这些标记不能被重写或用于自定义运算符。 - -运算符两侧的空白被用来区分该运算符是否为前缀运算符(*prefix operator*)、后缀运算符(*postfix operator*)或二元运算符(*binary operator*)。规则总结如下: - -* 如果运算符两侧都有空白或两侧都无空白,将被看作二元运算符。例如:`a+b` 和 `a + b` 中的运算符 `+` 被看作二元运算符。 -* 如果运算符只有左侧空白,将被看作前缀一元运算符。例如 `a ++b` 中的 `++` 被看作前缀一元运算符。 -* 如果运算符只有右侧空白,将被看作后缀一元运算符。例如 `a++ b` 中的 `++` 被看作后缀一元运算符。 -* 如果运算符左侧没有空白并紧跟 `.`,将被看作后缀一元运算符。例如 `a++.b` 中的 `++` 被看作后缀一元运算符(同理, `a++ . b` 中的 `++` 是后缀一元运算符而 `a ++ .b` 中的 `++` 不是). - -鉴于这些规则,运算符前的字符 `(`、`[` 和 `{` ;运算符后的字符 `)`、`]` 和 `}` 以及字符 `,`、`;` 和 `:` 都将用于空白检测。 - -以上规则需注意一点,如果运算符 `!` 或 `?` 左侧没有空白,则不管右侧是否有空白都将被看作后缀运算符。如果将 `?` 用作可选类型(*optional type*)修饰,左侧必须无空白。如果用于条件运算符 `? :`,必须两侧都有空白。 - -在特定构成中 ,以 `<` 或 `>` 开头的运算符会被分离成两个或多个标记,剩余部分以同样的方式会被再次分离。因此,在 `Dictionary>` 中没有必要添加空白来消除闭合字符 `>` 的歧义。在这个例子中, 闭合字符 `>` 被看作单字符标记,而不会被误解为移位运算符 `>>`。 - -要学习如何自定义新的运算符,请参考 [自定义操作符](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)。 - -> 运算符语法语法 -> *运算符* → [*运算符字符*](LexicalStructure.html#operator_character) [*运算符*](LexicalStructure.html#operator) _可选_ -> *运算符字符* → **/** | **=** | **-** | **+** | **!** | ***** | **%** | **<** | **>** | **&** | **|** | **^** | **~** | **.** -> *二元运算符* → [*运算符*](LexicalStructure.html#operator) -> *前置运算符* → [*运算符*](LexicalStructure.html#operator) -> *后置运算符* → [*运算符*](LexicalStructure.html#operator) +> 翻译:[superkam](https://github.com/superkam) +> 校对:[numbbbbb](https://github.com/numbbbbb) + +# 词法结构 +----------------- + +本页包含内容: + +- [空白与注释(*Whitespace and Comments*)](#whitespace_and_comments) +- [标识符(*Identifiers*)](#identifiers) +- [关键字(*Keywords*)](#keywords) +- [字面量(*Literals*)](#literals) +- [运算符(*Operators*)](#operators) + +Swift 的“词法结构(*lexical structure*)”描述了能构成该语言中合法标记(*tokens*)的字符序列。这些合法标记组成了语言中最底层的构建基块,并在之后的章节中用于描述语言的其他部分。 + +通常情况下,标记是在随后将介绍的语法约束下,由 Swift 源文件的输入文本中提取可能的最长子串生成。这种方法称为“最长匹配项(*longest match*)”,或者“最大适合”(*maximal munch*)。 + + +## 空白与注释 + +空白(*whitespace*)有两个用途:分隔源文件中的标记和帮助区分运算符属于前缀还是后缀(参见 [运算符](#operators)),在其他情况下则会被忽略。以下的字符会被当作空白:空格(*space*)(U+0020)、换行符(*line feed*)(U+000A)、回车符(*carriage return*)(U+000D)、水平制表符(*horizontal tab*)(U+0009)、垂直制表符(*vertical tab*)(U+000B)、换页符(*form feed*)(U+000C)以及空(*null*)(U+0000)。 + +注释(*comments*)被编译器当作空白处理。单行注释由 `//` 开始直至遇到换行符(*line feed*)(U+000A)或者回车符(*carriage return*)(U+000D)。多行注释由 `/*` 开始,以 `*/` 结束。注释允许嵌套,但注释标记必须匹配。 + + +## 标识符 + +标识符(*identifiers*)可以由以下的字符开始:大写或小写的字母 `A` 到 `Z`、下划线 `_`、基本多文种平面(*Basic Multilingual Plane*)中的 Unicode 非组合字符以及基本多文种平面以外的非专用区(*Private Use Area*)字符。首字符之后,允许使用数字和 Unicode 字符组合。 + +使用保留字(*reserved word*)作为标识符,需要在其前后增加反引号 `` `。例如,`class` 不是合法的标识符,但可以使用 \`class\`。反引号不属于标识符的一部分,\`x\` 和 `x` 表示同一标识符。 + +闭包(*closure*)中如果没有明确指定参数名称,参数将被隐式命名为 `$0`、`$1`、`$2`等等。 这些命名在闭包作用域范围内是合法的标识符。 + +> 标识符语法 + +> *标识符* → [*头部标识符*](#identifier_head) [*标识符字符组*](#identifier_characters)可选 +> *标识符* → \`[*头部标识符*](#identifier_head) [*标识符字符组*](#identifier_characters)可选\` +> *标识符* → [*隐式参数名*](#implicit_parameter_name) +> *标识符列表* → [*标识符*](#identifier) | [*标识符*](#identifier) **,** [*标识符列表*](#identifier_list) + +> *头部标识符* → 大写或小写字母 A - Z +> *头部标识符* → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2–U+00B5, or U+00B7–U+00BA +> *头部标识符* → U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, or U+00F8–U+00FF +> *头部标识符* → U+0100–U+02FF, U+0370–U+167F, U+1681–U+180D, or U+180F–U+1DBF +> *头部标识符* → U+1E00–U+1FFF +> *头部标识符* → U+200B–U+200D, U+202A–U+202E, U+203F–U+2040, U+2054, or U+2060–U+206F +> *头部标识符* → U+2070–U+20CF, U+2100–U+218F, U+2460–U+24FF, or U+2776–U+2793 +> *头部标识符* → U+2C00–U+2DFF or U+2E80–U+2FFF +> *头部标识符* → U+3004–U+3007, U+3021–U+302F, U+3031–U+303F, or U+3040–U+D7FF +> *头部标识符* → U+F900–U+FD3D, U+FD40–U+FDCF, U+FDF0–U+FE1F, or U+FE30–U+FE44 +> *头部标识符* → U+FE47–U+FFFD +> *头部标识符* → U+10000–U+1FFFD, U+20000–U+2FFFD, U+30000–U+3FFFD, or U+40000–U+4FFFD +> *头部标识符* → U+50000–U+5FFFD, U+60000–U+6FFFD, U+70000–U+7FFFD, or U+80000–U+8FFFD +> *头部标识符* → U+90000–U+9FFFD, U+A0000–U+AFFFD, U+B0000–U+BFFFD, or U+C0000–U+CFFFD +> *头部标识符* → U+D0000–U+DFFFD or U+E0000–U+EFFFD +> *标识符字符* → 数值 0 - 9 +> *标识符字符* → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+FE2F +> *标识符字符* → [*头部标识符*](#identifier_head) + +> *标识符字符组* → [*标识符字符*](#identifier_character) [*标识符字符列表*](#identifier_characters)可选 + +## 关键字和符号 + +下面这些被保留的关键字(*keywords*)不允许用作标识符,除非被反引号转义,具体描述请参考 [标识符](#identifiers)。 + +* **用在声明中的关键字:** *class*、*deinit*、*enum*、*extension*、*func*、*import*、*init*、*let*、*protocol*、*static*、*struct*、*subscript*、*typealias*、*var* +* **用在语句中的关键字:** *break*、*case*、*continue*、*default*、*do*、*else*、*fallthrough*、*if*、*in*、*for*、*return*、*switch*、*where*、*while* +* **用在表达式和类型中的关键字:** *as*、*dynamicType*、*is*、*new*、*super*、*self*、*Self*、*Type*、*\_\_COLUMN\_\_*、*\_\_FILE\_\_*、*\_\_FUNCTION\_\_*、*\_\_LINE\_\_* +* **用在模式中的关键字:** *\_* +* **特定上下文中被保留的关键字:** *associativity*、*didSet*、*get*、*infix*、*inout*、*left*、*mutating*、*none*、*nonmutating*、*operator*、*override*、*postfix*、*precedence*、*prefix*、*right*、*set*、*unowned*、*unowned(safe)*、*unowned(unsafe)*、*weak*、*willSet*,这些关键字在特定上下文之外可以被用于标识符。 + +以下标记被当作保留符号,不能用于自定义操作符:`(`、`)`、`{`、`}`、`[`、`]`、`.`、`,`、`:`、`;`、`=`、`@`、`#`、`&(作为前缀操作符)`、`->`、`` `、`?` 和 `!(作为后缀操作符)`。 + + +## 字面量 + +字面量是用来表示源码中某种特定类型的值,比如一个数字或字符串。 + +下面是字面量的一些示例: + +```swift +42 // 整型字面量 +3.14159 // 浮点型字面量 +"Hello, world!" // 字符串型字面量 +true // 布尔型字面量 +``` + +字面量本身并不包含类型信息。事实上,一个字面量会被解析为拥有无限的精度,然后 Swift 的类型推导会尝试去推导出这个字面量的类型。比如,在 `let x: Int8 = 42` 这个声明中,Swift 使用了显式类型注解(`: Int8`)来推导出 `42` 这个整型字面量的类型是 `Int8`。如果没有可用的类型信息, Swift 则会从标准库中定义的字面量类型中推导出一个默认的类型。整型字面量的默认类型是 `Int`,浮点型字面量的默认类型是 `Double`,字符串型字面量的默认类型是 `String`,布尔型字面量的默认类型是 `Bool`。比如,在 `let str = "Hello, world"` 这个声明中,字符串 `"Hello, world"`的默认推导类型就是 `String`。 + +当为一个字面量值指定了类型注解的时候,这个注解的类型必须能通过这个字面量值实例化后得到。也就是说,这个类型必须遵守这些 Swift 标准库协议中的一个:整型字面量的`IntegerLiteralConvertible`协议、符点型字面量的`FloatingPointLiteralConvertible`协议、字符串字面量的`StringLiteralConvertible`协议以及布尔型字面量的`BooleanLiteralConvertible`协议。比如,`Int8` 遵守了 `IntegerLiteralConvertible`协议,因此它能在 `let x: Int8 = 42` 这个声明中作为整型字面量 `42` 的类型注解。 + +> 字面量语法 +> *字面量* → [*数字型字面量*](#numeric_literal) | [*字符串型字面量*](#string_literal) | [*布尔型字面量*](#boolean_literal) | [*nil型字面量*](#nil_literal) + +> *数字型字面量* → -可选[*整型字面量*](#integer_literal) | -可选[*符点型字面量*](#floating_point_literal) +> *布尔型字面量* → **true** | **false** +> *nil型字面量* → **nil** + +### 整型字面量 + +整型字面量(*integer literals*)表示未指定精度整型数的值。整型字面量默认用十进制表示,可以加前缀来指定其他的进制,二进制字面量加 `0b`,八进制字面量加 `0o`,十六进制字面量加 `0x`。 + +十进制字面量包含数字 `0` 至 `9`。二进制字面量只包含 `0` 或 `1`,八进制字面量包含数字 `0` 至 `7`,十六进制字面量包含数字 `0` 至 `9` 以及字母 `A` 至 `F` (大小写均可)。 + +负整数的字面量在整型字面量前加减号 `-`,比如 `-42`。 + +整型字面面可以使用下划线 `_` 来增加数字的可读性,下划线会被系统忽略,因此不会影响字面量的值。同样地,也可以在数字前加 `0`,并不会影响字面量的值。 + +除非特别指定,整型字面量的默认推导类型为 Swift 标准库类型中的 `Int`。Swift 标准库还定义了其他不同长度以及是否带符号的整数类型,请参考 [整数类型](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID323)。 + +> 整型字面量语法 +> *整型字面量* → [*二进制字面量*](#binary_literal) +> *整型字面量* → [*八进制字面量*](#octal_literal) +> *整型字面量* → [*十进制字面量*](#decimal_literal) +> *整型字面量* → [*十六进制字面量*](#hexadecimal_literal) + +> *二进制字面量* → **0b** [*二进制数字*](#binary_digit) [*二进制字面量字符组*](#binary_literal_characters)可选 +> *二进制数字* → 数值 0 到 1 +> *二进制字面量字符* → [*二进制数字*](#binary_digit) | _ +> *二进制字面量字符组* → [*二进制字面量字符*](#binary_literal_character) [*二进制字面量字符组*](#binary_literal_characters)可选 + +> *十进制字面量* → [*十进制数字*](#decimal_digit) [*十进制字符组*](#decimal_literal_characters)可选 +> *十进制数字* → 数值 0 到 9 +> *十进制数字列表* → [*十进制数字*](#decimal_digit) [*十进制数字列表*](#decimal_digits)可选 +> *十进制字符* → [*十进制数字*](#decimal_digit) | _ +> *十进制字符列表* → [*十进制字符*](#decimal_literal_character) [*十进制字符列表*](#decimal_literal_characters)可选 + +> *十六进制字面量* → **0x** [*十六进制数字*](#hexadecimal_digit) [*十六进制字面量字符列表*](#hexadecimal_literal_characters)可选 +> *十六进制数字* → 数值 0 到 9, 字母 a 到 f, 或 A 到 F +> *十六进制字符* → [*十六进制数字*](#hexadecimal_digit) | _ +> *十六进制字面量字符列表* → [*十六进制字符*](#hexadecimal_literal_character) [*十六进制字面量字符列表*](#hexadecimal_literal_characters)可选 + +### 浮点型字面量 + +浮点型字面量(*floating-point literals*)表示未指定精度浮点数的值。 + +浮点型字面量默认用十进制表示(无前缀),也可以用十六进制表示(加前缀 `0x`)。 + +十进制浮点型字面量(*decimal floating-point literals*)由十进制数字串后跟小数部分或指数部分(或两者皆有)组成。十进制小数部分由小数点 `.` 后跟十进制数字串组成。指数部分由大写或小写字母 `e` 为前缀后跟十进制数字串组成,这串数字表示 `e` 之前的数量乘以 10 的几次方。例如:`1.25e2` 表示 `1.25 ⨉ 10^2`,也就是 `125.0`;同样,`1.25e-2` 表示 `1.25 ⨉ 10^-2`,也就是 `0.0125`。 + +十六进制浮点型字面量(*hexadecimal floating-point literals*)由前缀 `0x` 后跟可选的十六进制小数部分以及十六进制指数部分组成。十六进制小数部分由小数点后跟十六进制数字串组成。指数部分由大写或小写字母 `p` 为前缀后跟十进制数字串组成,这串数字表示 `p` 之前的数量乘以 2 的几次方。例如:`0xFp2` 表示 `15 ⨉ 2^2`,也就是 `60`;同样,`0xFp-2` 表示 `15 ⨉ 2^-2`,也就是 `3.75`。 + +负的浮点型字面量由一元运算符减号 `-` 和浮点型字面量组成,例如 `-42.5`。 + +浮点型字面量允许使用下划线 `_` 来增强数字的可读性,下划线会被系统忽略,因此不会影响字面量的值。同样地,也可以在数字前加 `0`,并不会影响字面量的值。 + +除非特别指定,浮点型字面量的默认推导类型为 Swift 标准库类型中的 `Double`,表示64位浮点数。Swift 标准库也定义了 `Float` 类型,表示32位浮点数。 + +> 浮点型字面量语法 +> *浮点数字面量* → [*十进制字面量*](#decimal_literal) [*十进制分数*](#decimal_fraction)可选 [*十进制指数*](#decimal_exponent)可选 +> *浮点数字面量* → [*十六进制字面量*](#hexadecimal_literal) [*十六进制分数*](#hexadecimal_fraction)可选 [*十六进制指数*](#hexadecimal_exponent) + +> *十进制分数* → **.** [*十进制字面量*](#decimal_literal) +> *十进制指数* → [*浮点数e*](#floating_point_e) [*正负号*](#sign)可选 [*十进制字面量*](#decimal_literal) + +> *十六进制分数* → **.** [*十六进制数字*](#hexadecimal_digit) [*十六进制字面量字符列表*](#hexadecimal_literal_characters)可选 +> *十六进制指数* → [*浮点数p*](#floating_point_p) [*正负号*](#sign)可选 [*十进制字面量*](#decimal_literal) + +> *浮点数e* → **e** | **E** +> *浮点数p* → **p** | **P** +> *正负号* → **+** | **-** + + +### 字符串型字面量 + +字符串型字面量(*string literal*)由被包在双引号中的一串字符组成,形式如下: + +``` +"characters" +``` + +字符串型字面量中不能包含未转义的双引号 (`"`)、未转义的反斜线(`\`)、回车符(*carriage return*)或换行符(*line feed*)。 + +可以在字符串字面量中使用的转义特殊符号如下: + +* 空字符(Null Character)`\0` +* 反斜线(Backslash)`\\` +* 水平制表符(Horizontal Tab)`\t` +* 换行符(Line Feed)`\n` +* 回车符(Carriage Return)`\r` +* 双引号(Double Quote)`\"` +* 单引号(Single Quote)`\'` +* Unicode标量 `\u{n}`,n为一到八位的十六进制数字 + +字符串字面量允许在反斜杠小括号 `\()` 中插入表达式的值。插入表达式(*interpolated expression*)不能包含未转义的双引号 `"`、未转义的反斜线 `\`、回车符或者换行符。表达式结果的类型必须在 *String* 类中有对应的初始化方法。 + +例如,以下所有字符串字面量的值都是相同的: + +``` +"1 2 3" +"1 2 \(3)" +"1 2 \(1 + 2)" +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)。 + +> 字符型字面量语法 +> *字符串字面量* → **"** [*引用文本*](#quoted_text)可选 **"** + +> *引用文本* → [*引用文本条目*](#quoted_text_item) [*引用文本*](#quoted_text) 可选 +> *引用文本条目* → [*转义字符*](#escaped_character) +> *引用文本条目* → **\(** [*表达式*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID383) **)** +> *引用文本条目* → **除了"­, \­, U+000A, 或者 U+000D的所有Unicode的字符** +> *转义字符* → **\0** | **\\** | **\t** | **\n** | **\r** | **\"** | **\'** +> *转义字符* → **\u {** [*unicode标量数字*](#unicode_scalar_digits) **}** +> *unicode标量数字* → 一到八位的十六进制数字 + + +## 运算符 + +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) 中进行了阐述。这一小节将描述哪些字符能用于自定义运算符。 + +自定义运算符可以由以下其中之一的 ASCII 字符 `/`、`=`、 `-`、`+`、`!`、`*`、`%`、`<`、`>`、`&`、`|`、`^`、`?` 以及 `~`, 或者后面语法中规定的任一个 Unicode 字符开始。在第一个字符之后,允许使用组合型 Unicode 字符。也可以使用两个或者多个的点号来自定义运算符(比如, `....`)。虽然可以自定义包含问号`?`的运算符,但是这个运算符不能只包含单独的一个问号。 + + 注意: + 以下这些标记 =, ->, //, /*, */, ., <(前缀运算符), &, and ?, ?(中缀运算符), >(后缀运算符), ! 以及 ? 是被系统保留的。这些标记不能被重载,也不能用于自定义操作符。 + +运算符两侧的空白被用来区分该运算符是否为前缀运算符(*prefix operator*)、后缀运算符(*postfix operator*)或二元运算符(*binary operator*)。规则总结如下: + +* 如果运算符两侧都有空白或两侧都无空白,将被看作二元运算符。例如:`a+b` 和 `a + b` 中的运算符 `+` 被看作二元运算符。 +* 如果运算符只有左侧空白,将被看作前缀一元运算符。例如 `a ++b` 中的 `++` 被看作前缀一元运算符。 +* 如果运算符只有右侧空白,将被看作后缀一元运算符。例如 `a++ b` 中的 `++` 被看作后缀一元运算符。 +* 如果运算符左侧没有空白并紧跟 `.`,将被看作后缀一元运算符。例如 `a++.b` 中的 `++` 被看作后缀一元运算符(即上式被视为 `a++ .b` 而非 `a ++ .b`)。 + +鉴于这些规则,运算符前的字符 `(`、`[` 和 `{` ;运算符后的字符 `)`、`]` 和 `}` 以及字符 `,`、`;` 和 `:` 都被视为空白。 + +以上规则需注意一点,如果预定义运算符 `!` 或 `?` 左侧没有空白,则不管右侧是否有空白都将被看作后缀运算符。如果将 `?` 用作可选链(*optional-chaining*)操作符,左侧必须无空白。如果用于条件运算符 `? :`,必须两侧都有空白。 + +在某些特定的构造中 ,以 `<` 或 `>` 开头的运算符会被分离成两个或多个标记,剩余部分以同样的方式会被再次分离。因此,在 `Dictionary>` 中没有必要添加空白来消除闭合字符 `>` 的歧义。在这个例子中, 闭合字符 `>` 不会被视为单独的标记,因而不会被误解析为 `>>` 运算符的一部分。 + +要学习如何自定义运算符,请参考 [自定义操作符](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)。 + +> 运算符语法语法 +> *运算符* → [*头部运算符*](#operator_head) [*运算符字符组*](#operator_characters)可选 +> *运算符* → [*头部点运算符*](#dot_operator_head) [*点运算符字符组*](#dot_operator_characters)可选 + +> *头部运算符* → **/** | **=** | **+** | **!** |**\*** | **%** |**<** | **>** |**&** | **|** |**/** | **~** | **?** | +> *头部运算符* → U+00A1–U+00A7 +> *头部运算符* → U+00A9 or U+00AB +> *头部运算符* → U+00AC or U+00AE +> *头部运算符* → U+00B0–U+00B1, U+00B6, U+00BB, U+00BF, U+00D7, or U+00F7 +> *头部运算符* → U+2016–U+2017 or U+2020–U+2027 +> *头部运算符* → U+2030–U+203E +> *头部运算符* → U+2041–U+2053 +> *头部运算符* → U+2055–U+205E +> *头部运算符* → U+2190–U+23FF +> *头部运算符* → U+2500–U+2775 +> *头部运算符* → U+2794–U+2BFF +> *头部运算符* → U+2E00–U+2E7F +> *头部运算符* → U+3001–U+3003 +> *头部运算符* → U+3008–U+3030 + +> *运算符字符* → [*头部运算符*](#operator_head) +> *运算符字符* → U+0300–U+036F +> *运算符字符* → U+1DC0–U+1DFF +> *运算符字符* → U+20D0–U+20FF +> *运算符字符* → U+FE00–U+FE0F +> *运算符字符* → U+FE20–U+FE2F +> *运算符字符* → U+E0100–U+E01EF + +> *运算符字符组* → [*运算符字符*](#operator_character) [*运算符字符组*](#operator_characters)可选 + +> *头部点运算符* → **..** +> *头部点运算符字符* → . | [*运算符字符*](#operator_character) +> *头部点运算符字符组* → [*点运算符字符*](#dot_operator_character) [*点运算符字符组*](#dot_operator_characters)可选 + +> *二元运算符* → [*运算符*](#operator) +> *前置运算符* → [*运算符*](#operator) +> *后置运算符* → [*运算符*](#operator) From a0303ee3074e02743b66ce49d8c13fa7282ad578 Mon Sep 17 00:00:00 2001 From: justaway Date: Mon, 29 Jun 2015 20:36:57 +0800 Subject: [PATCH 25/50] =?UTF-8?q?=E9=87=8D=E6=96=B0=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter3/02_Lexical_Structure.md | 98 ++++++++++++------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/source/chapter3/02_Lexical_Structure.md b/source/chapter3/02_Lexical_Structure.md index 0fd074a2..76f1ae44 100755 --- a/source/chapter3/02_Lexical_Structure.md +++ b/source/chapter3/02_Lexical_Structure.md @@ -34,11 +34,11 @@ Swift 的“词法结构(*lexical structure*)”描述了能构成该语言 > 标识符语法 -> *标识符* → [*头部标识符*](#identifier_head) [*标识符字符组*](#identifier_characters)可选 +> *标识符* → [*头部标识符*](#identifier_head) [*标识符字符组*](#identifier_characters)可选 > *标识符* → \`[*头部标识符*](#identifier_head) [*标识符字符组*](#identifier_characters)可选\` > *标识符* → [*隐式参数名*](#implicit_parameter_name) -> *标识符列表* → [*标识符*](#identifier) | [*标识符*](#identifier) **,** [*标识符列表*](#identifier_list) - +> *标识符列表* → [*标识符*](#identifier) | [*标识符*](#identifier) **,** [*标识符列表*](#identifier_list) + > *头部标识符* → 大写或小写字母 A - Z > *头部标识符* → U+00A8, U+00AA, U+00AD, U+00AF, U+00B2–U+00B5, or U+00B7–U+00BA > *头部标识符* → U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, or U+00F8–U+00FF @@ -57,9 +57,9 @@ Swift 的“词法结构(*lexical structure*)”描述了能构成该语言 > *标识符字符* → 数值 0 - 9 > *标识符字符* → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+FE2F > *标识符字符* → [*头部标识符*](#identifier_head) - + > *标识符字符组* → [*标识符字符*](#identifier_character) [*标识符字符列表*](#identifier_characters)可选 - > *隐式参数名* → **$** [*十进制数字列表*](#decimal_digits) @@ -94,10 +94,10 @@ true // 布尔型字面量 当为一个字面量值指定了类型注解的时候,这个注解的类型必须能通过这个字面量值实例化后得到。也就是说,这个类型必须遵守这些 Swift 标准库协议中的一个:整型字面量的`IntegerLiteralConvertible`协议、符点型字面量的`FloatingPointLiteralConvertible`协议、字符串字面量的`StringLiteralConvertible`协议以及布尔型字面量的`BooleanLiteralConvertible`协议。比如,`Int8` 遵守了 `IntegerLiteralConvertible`协议,因此它能在 `let x: Int8 = 42` 这个声明中作为整型字面量 `42` 的类型注解。 > 字面量语法 -> *字面量* → [*数字型字面量*](#numeric_literal) | [*字符串型字面量*](#string_literal) | [*布尔型字面量*](#boolean_literal) | [*nil型字面量*](#nil_literal) - -> *数字型字面量* → -可选[*整型字面量*](#integer_literal) | -可选[*符点型字面量*](#floating_point_literal) -> *布尔型字面量* → **true** | **false** +> *字面量* → [*数字型字面量*](#numeric_literal) | [*字符串型字面量*](#string_literal) | [*布尔型字面量*](#boolean_literal) | [*nil型字面量*](#nil_literal) + +> *数字型字面量* → -可选[*整型字面量*](#integer_literal) | -可选[*符点型字面量*](#floating_point_literal) +> *布尔型字面量* → **true** | **false** > *nil型字面量* → **nil** ### 整型字面量 @@ -120,23 +120,23 @@ true // 布尔型字面量 > *二进制字面量* → **0b** [*二进制数字*](#binary_digit) [*二进制字面量字符组*](#binary_literal_characters)可选 > *二进制数字* → 数值 0 到 1 -> *二进制字面量字符* → [*二进制数字*](#binary_digit) | _ +> *二进制字面量字符* → [*二进制数字*](#binary_digit) | _ > *二进制字面量字符组* → [*二进制字面量字符*](#binary_literal_character) [*二进制字面量字符组*](#binary_literal_characters)可选 - +> *八进制字面量* → **0o** [*八进字数字*](#octal_digit) [*八进制字符列表*](#octal_literal_characters)可选 > *八进字数字* → 数值 0 到 7 -> *八进制字符* → [*八进字数字*](#octal_digit) | _ +> *八进制字符* → [*八进字数字*](#octal_digit) | _ > *八进制字符组* → [*八进制字符*](#octal_literal_character) [*八进制字符列表*](#octal_literal_characters)可选 - -> *十进制字面量* → [*十进制数字*](#decimal_digit) [*十进制字符组*](#decimal_literal_characters)可选 + +> *十进制字面量* → [*十进制数字*](#decimal_digit) [*十进制字符组*](#decimal_literal_characters)可选 > *十进制数字* → 数值 0 到 9 > *十进制数字列表* → [*十进制数字*](#decimal_digit) [*十进制数字列表*](#decimal_digits)可选 -> *十进制字符* → [*十进制数字*](#decimal_digit) | _ +> *十进制字符* → [*十进制数字*](#decimal_digit) | _ > *十进制字符列表* → [*十进制字符*](#decimal_literal_character) [*十进制字符列表*](#decimal_literal_characters)可选 - + > *十六进制字面量* → **0x** [*十六进制数字*](#hexadecimal_digit) [*十六进制字面量字符列表*](#hexadecimal_literal_characters)可选 > *十六进制数字* → 数值 0 到 9, 字母 a 到 f, 或 A 到 F -> *十六进制字符* → [*十六进制数字*](#hexadecimal_digit) | _ +> *十六进制字符* → [*十六进制数字*](#hexadecimal_digit) | _ > *十六进制字面量字符列表* → [*十六进制字符*](#hexadecimal_literal_character) [*十六进制字面量字符列表*](#hexadecimal_literal_characters)可选 ### 浮点型字面量 @@ -156,9 +156,9 @@ true // 布尔型字面量 除非特别指定,浮点型字面量的默认推导类型为 Swift 标准库类型中的 `Double`,表示64位浮点数。Swift 标准库也定义了 `Float` 类型,表示32位浮点数。 > 浮点型字面量语法 -> *浮点数字面量* → [*十进制字面量*](#decimal_literal) [*十进制分数*](#decimal_fraction)可选 [*十进制指数*](#decimal_exponent)可选 +> *浮点数字面量* → [*十进制字面量*](#decimal_literal) [*十进制分数*](#decimal_fraction)可选 [*十进制指数*](#decimal_exponent)可选 > *浮点数字面量* → [*十六进制字面量*](#hexadecimal_literal) [*十六进制分数*](#hexadecimal_fraction)可选 [*十六进制指数*](#hexadecimal_exponent) - + > *十进制分数* → **.** [*十进制字面量*](#decimal_literal) > *十进制指数* → [*浮点数e*](#floating_point_e) [*正负号*](#sign)可选 [*十进制字面量*](#decimal_literal) @@ -211,7 +211,7 @@ let x = 3; "1 2 \(x)" > *引用文本条目* → [*转义字符*](#escaped_character) > *引用文本条目* → **\(** [*表达式*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID383) **)** > *引用文本条目* → **除了"­, \­, U+000A, 或者 U+000D的所有Unicode的字符** -> *转义字符* → **\0** | **\\** | **\t** | **\n** | **\r** | **\"** | **\'** +> *转义字符* → **\0** | **\\** | **\t** | **\n** | **\r** | **\"** | **\'** > *转义字符* → **\u {** [*unicode标量数字*](#unicode_scalar_digits) **}** > *unicode标量数字* → 一到八位的十六进制数字 @@ -242,36 +242,36 @@ Swift 标准库定义了许多可供使用的运算符,其中大部分在 [基 > 运算符语法语法 > *运算符* → [*头部运算符*](#operator_head) [*运算符字符组*](#operator_characters)可选 -> *运算符* → [*头部点运算符*](#dot_operator_head) [*点运算符字符组*](#dot_operator_characters)可选 - +> *运算符* → [*头部点运算符*](#dot_operator_head) [*点运算符字符组*](#dot_operator_characters)可选 + > *头部运算符* → **/** | **=** | **+** | **!** |**\*** | **%** |**<** | **>** |**&** | **|** |**/** | **~** | **?** | -> *头部运算符* → U+00A1–U+00A7 -> *头部运算符* → U+00A9 or U+00AB -> *头部运算符* → U+00AC or U+00AE -> *头部运算符* → U+00B0–U+00B1, U+00B6, U+00BB, U+00BF, U+00D7, or U+00F7 -> *头部运算符* → U+2016–U+2017 or U+2020–U+2027 -> *头部运算符* → U+2030–U+203E -> *头部运算符* → U+2041–U+2053 -> *头部运算符* → U+2055–U+205E -> *头部运算符* → U+2190–U+23FF -> *头部运算符* → U+2500–U+2775 -> *头部运算符* → U+2794–U+2BFF -> *头部运算符* → U+2E00–U+2E7F -> *头部运算符* → U+3001–U+3003 +> *头部运算符* → U+00A1–U+00A7 +> *头部运算符* → U+00A9 or U+00AB +> *头部运算符* → U+00AC or U+00AE +> *头部运算符* → U+00B0–U+00B1, U+00B6, U+00BB, U+00BF, U+00D7, or U+00F7 +> *头部运算符* → U+2016–U+2017 or U+2020–U+2027 +> *头部运算符* → U+2030–U+203E +> *头部运算符* → U+2041–U+2053 +> *头部运算符* → U+2055–U+205E +> *头部运算符* → U+2190–U+23FF +> *头部运算符* → U+2500–U+2775 +> *头部运算符* → U+2794–U+2BFF +> *头部运算符* → U+2E00–U+2E7F +> *头部运算符* → U+3001–U+3003 > *头部运算符* → U+3008–U+3030 - -> *运算符字符* → [*头部运算符*](#operator_head) -> *运算符字符* → U+0300–U+036F -> *运算符字符* → U+1DC0–U+1DFF -> *运算符字符* → U+20D0–U+20FF -> *运算符字符* → U+FE00–U+FE0F -> *运算符字符* → U+FE20–U+FE2F -> *运算符字符* → U+E0100–U+E01EF - -> *运算符字符组* → [*运算符字符*](#operator_character) [*运算符字符组*](#operator_characters)可选 - -> *头部点运算符* → **..** -> *头部点运算符字符* → . | [*运算符字符*](#operator_character) + +> *运算符字符* → [*头部运算符*](#operator_head) +> *运算符字符* → U+0300–U+036F +> *运算符字符* → U+1DC0–U+1DFF +> *运算符字符* → U+20D0–U+20FF +> *运算符字符* → U+FE00–U+FE0F +> *运算符字符* → U+FE20–U+FE2F +> *运算符字符* → U+E0100–U+E01EF + +> *运算符字符组* → [*运算符字符*](#operator_character) [*运算符字符组*] (#operator_characters)可选 + +> *头部点运算符* → **..** +> *头部点运算符字符* → . | [*运算符字符*](#operator_character) > *头部点运算符字符组* → [*点运算符字符*](#dot_operator_character) [*点运算符字符组*](#dot_operator_characters)可选 > *二元运算符* → [*运算符*](#operator) From 8422ddf081bb33ab95006647e33ed46428e9ea3c Mon Sep 17 00:00:00 2001 From: chenYuheng Date: Mon, 29 Jun 2015 21:03:33 +0800 Subject: [PATCH 26/50] =?UTF-8?q?=E6=B3=9B=E5=9E=8B=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=BA=86=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=92=8C=E6=96=87=E6=9C=AC=E6=9B=B4=E6=96=B0=E7=9A=84=E5=9C=B0?= =?UTF-8?q?=E6=96=B9=EF=BC=8C=E8=BF=98=E5=89=A9=E4=B8=8B=E5=9B=9B=E4=B8=AA?= =?UTF-8?q?=E5=B0=8F=E8=8A=82=E6=B2=A1=E6=9C=89=E5=AE=8C=E6=88=90=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/23_Generics.md | 53 +++++++++++++++++----------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/source/chapter2/23_Generics.md b/source/chapter2/23_Generics.md index c114a436..ec031e3e 100644 --- a/source/chapter2/23_Generics.md +++ b/source/chapter2/23_Generics.md @@ -27,7 +27,7 @@ 这里是一个标准的,非泛型函数`swapTwoInts`,用来交换两个Int值: ```swift -func swapTwoInts(inout a: Int, inout b: Int) { +func swapTwoInts(inout a: Int, inout _ b: Int) { let temporaryA = a a = b b = temporaryA @@ -36,7 +36,7 @@ func swapTwoInts(inout a: Int, inout b: Int) { 这个函数使用写入读出(in-out)参数来交换`a`和`b`的值,请参考[写入读出参数](../chapter2/06_Functions.html)。 -`swapTwoInts`函数可以交换`b`的原始值到`a`,也可以交换a的原始值到`b`,你可以调用这个函数交换两个`Int`变量值: +`swapTwoInts(_:_:)`函数可以交换`b`的原始值到`a`,也可以交换a的原始值到`b`,你可以调用这个函数交换两个`Int`变量值: ```swift var someInt = 3 @@ -47,23 +47,23 @@ println("someInt is now \(someInt), and anotherInt is now \(anotherInt)") ``` -`swapTwoInts`函数是非常有用的,但是它只能交换`Int`值,如果你想要交换两个`String`或者`Double`,就不得不写更多的函数,如 `swapTwoStrings`和`swapTwoDoublesfunctions `,如同如下所示: +`swapTwoInts(_:_:)`函数是非常有用的,但是它只能交换`Int`值,如果你想要交换两个`String`或者`Double`,就不得不写更多的函数,如 `swapTwoStrings`和`swapTwoDoubles(_:_:)`,如同如下所示: ```swift -func swapTwoStrings(inout a: String, inout b: String) { +func swapTwoStrings(inout a: String, inout _ b: String) { let temporaryA = a a = b b = temporaryA } -func swapTwoDoubles(inout a: Double, inout b: Double) { +func swapTwoDoubles(inout a: Double, inout _ b: Double) { let temporaryA = a a = b b = temporaryA } ``` -你可能注意到 `swapTwoInts`、 `swapTwoStrings`和`swapTwoDoubles`函数功能都是相同的,唯一不同之处就在于传入的变量类型不同,分别是`Int`、`String`和`Double`。 +你可能注意到 `swapTwoInts`、 `swapTwoStrings`和`swapTwoDoubles(_:_:)`函数功能都是相同的,唯一不同之处就在于传入的变量类型不同,分别是`Int`、`String`和`Double`。 但实际应用中通常需要一个用处更强大并且尽可能的考虑到更多的灵活性单个函数,可以用来交换两个任何类型值,很幸运的是,泛型代码帮你解决了这种问题。(一个这种泛型函数后面已经定义好了。) @@ -73,29 +73,29 @@ func swapTwoDoubles(inout a: Double, inout b: Double) { ## 泛型函数 -`泛型函数`可以工作于任何类型,这里是一个上面`swapTwoInts`函数的泛型版本,用于交换两个值: +`泛型函数`可以工作于任何类型,这里是一个上面`swapTwoInts(_:_:)`函数的泛型版本,用于交换两个值: ```swift -func swapTwoValues(inout a: T, inout b: T) { +func swapTwoValues(inout a: T, inout _ b: T) { let temporaryA = a a = b b = temporaryA } ``` -`swapTwoValues`函数主体和`swapTwoInts`函数是一样的,它只在第一行稍微有那么一点点不同于`swapTwoInts`,如下所示: +`swapTwoValues(_:_:)`函数主体和`swapTwoInts(_:_:)`函数是一样的,它只在第一行稍微有那么一点点不同于`swapTwoInts`,如下所示: ```swift -func swapTwoInts(inout a: Int, inout b: Int) -func swapTwoValues(inout a: T, inout b: T) +func swapTwoInts(inout a: Int, inout _ b: Int) +func swapTwoValues(inout a: T, inout _ b: T) ``` -这个函数的泛型版本使用了占位类型名字(通常此情况下用字母`T`来表示)来代替实际类型名(如`Int`、`String`或`Double`)。占位类型名没有提示`T`必须是什么类型,但是它提示了`a`和`b`必须是同一类型`T`,而不管`T`表示什么类型。只有`swapTwoValues`函数在每次调用时所传入的实际类型才能决定`T`所代表的类型。 +这个函数的泛型版本使用了占位类型名字(通常此情况下用字母`T`来表示)来代替实际类型名(如`Int`、`String`或`Double`)。占位类型名没有提示`T`必须是什么类型,但是它提示了`a`和`b`必须是同一类型`T`,而不管`T`表示什么类型。只有`swapTwoValues(_:_:)`函数在每次调用时所传入的实际类型才能决定`T`所代表的类型。 -另外一个不同之处在于这个泛型函数名后面跟着的占位类型名字(T)是用尖括号括起来的(``)。这个尖括号告诉 Swift 那个`T`是`swapTwoValues`函数所定义的一个类型。因为`T`是一个占位命名类型,Swift 不会去查找命名为T的实际类型。 +另外一个不同之处在于这个泛型函数名后面跟着的占位类型名字(T)是用尖括号括起来的(``)。这个尖括号告诉 Swift 那个`T`是`swapTwoValues(_:_:)`函数所定义的一个类型。因为`T`是一个占位命名类型,Swift 不会去查找命名为T的实际类型。 -`swapTwoValues`函数除了要求传入的两个任何类型值是同一类型外,也可以作为`swapTwoInts`函数被调用。每次`swapTwoValues`被调用,T所代表的类型值都会传给函数。 +`swapTwoValues(_:_:)`函数除了要求传入的两个任何类型值是同一类型外,也可以作为`swapTwoInts`函数被调用。每次`swapTwoValues`被调用,T所代表的类型值都会传给函数。 在下面的两个例子中,`T`分别代表`Int`和`String`: @@ -103,26 +103,26 @@ func swapTwoValues(inout a: T, inout b: T) var someInt = 3 var anotherInt = 107 swapTwoValues(&someInt, &anotherInt) -// someInt is now 107, and anotherInt is now 3 +// someInt 现在等于 107, anotherInt 现在等于 3 ``` ```swift var someString = "hello" var anotherString = "world" swapTwoValues(&someString, &anotherString) -// someString is now "world", and anotherString is now "hello" +// someString 现在等于 "world", anotherString 现在等于 "hello" ``` >注意 -上面定义的函数`swapTwoValues`是受`swap`函数启发而实现的。`swap`函数存在于 Swift 标准库,并可以在其它类中任意使用。如果你在自己代码中需要类似`swapTwoValues`函数的功能,你可以使用已存在的交换函数`swap`函数。 +上面定义的函数`swapTwoValues(_:_:)`是受`swap`函数启发而实现的。`swap`函数存在于 Swift 标准库,并可以在其它类中任意使用。如果你在自己代码中需要类似`swapTwoValues(_:_:)`函数的功能,你可以使用已存在的交换函数`swap(_:_:)`函数。 ## 类型参数 在上面的`swapTwoValues`例子中,占位类型`T`是一种类型参数的示例。类型参数指定并命名为一个占位类型,并且紧随在函数名后面,使用一对尖括号括起来(如``)。 -一旦一个类型参数被指定,那么其可以被使用来定义一个函数的参数类型(如`swapTwoValues`函数中的参数`a`和`b`),或作为一个函数返回类型,或用作函数主体中的注释类型。在这种情况下,被类型参数所代表的占位类型不管函数任何时候被调用,都会被实际类型所替换(在上面`swapTwoValues`例子中,当函数第一次被调用时,`T`被`Int`替换,第二次调用时,被`String`替换。)。 +一旦一个类型参数被指定,那么其可以被使用来定义一个函数的参数类型(如`swapTwoValues(_:_:)`函数中的参数`a`和`b`),或作为一个函数返回类型,或用作函数主体中的注释类型。在这种情况下,被类型参数所代表的占位类型不管函数任何时候被调用,都会被实际类型所替换(在上面`swapTwoValues`例子中,当函数第一次被调用时,`T`被`Int`替换,第二次调用时,被`String`替换。)。 你可支持多个类型参数,命名在尖括号中,用逗号分开。 @@ -131,10 +131,10 @@ swapTwoValues(&someString, &anotherString) 在简单的情况下,泛型函数或泛型类型需要指定一个占位类型(如上面的`swapTwoValues`泛型函数,或一个存储单一类型的泛型集,如数组),通常用一单个字母`T`来命名类型参数。不过,你可以使用任何有效的标识符来作为类型参数名。 -如果你使用多个参数定义更复杂的泛型函数或泛型类型,那么使用更多的描述类型参数是非常有用的。例如,Swift 字典(Dictionary)类型有两个类型参数,一个是键,另外一个是值。如果你自己写字典,你或许会定义这两个类型参数为`KeyType`和`ValueType`,用来记住它们在你的泛型代码中的作用。 +如果你使用多个参数定义更复杂的泛型函数或泛型类型,那么使用更多的描述类型参数是非常有用的。例如,Swift 字典(Dictionary)类型有两个类型参数,一个是键,另外一个是值。如果你自己写字典,你或许会定义这两个类型参数为`Key`和`Value`,用来记住它们在你的泛型代码中的作用。 >注意 -请始终使用大写字母开头的驼峰式命名法(例如`T`和`KeyType`)来给类型参数命名,以表明它们是类型的占位符,而非类型值。 +请始终使用大写字母开头的驼峰式命名法(例如`T`和`Key`)来给类型参数命名,以表明它们是类型的占位符,而非类型值。 ## 泛型类型 @@ -145,7 +145,7 @@ swapTwoValues(&someString, &anotherString) 这部分向你展示如何写一个泛型集类型--`Stack`(栈)。一个栈是一系列值域的集合,和`Array`(数组)类似,但其是一个比 Swift 的`Array`类型更多限制的集合。一个数组可以允许其里面任何位置的插入/删除操作,而栈,只允许在集合的末端添加新的项(如同*push*一个新值进栈)。同样的一个栈也只能从末端移除项(如同*pop*一个值出栈)。 >注意 -栈的概念已被`UINavigationController`类使用来模拟试图控制器的导航结构。你通过调用`UINavigationController`的`pushViewController:animated:`方法来为导航栈添加(add)新的试图控制器;而通过`popViewControllerAnimated:`的方法来从导航栈中移除(pop)某个试图控制器。每当你需要一个严格的`后进先出`方式来管理集合,堆栈都是最实用的模型。 +栈的概念已被`UINavigationController`类使用来模拟试图控制器的导航结构。你通过调用`UINavigationController`的`pushViewController(_:animated:)`方法来为导航栈添加(add)新的试图控制器;而通过`popViewControllerAnimated(_:)`的方法来从导航栈中移除(pop)某个试图控制器。每当你需要一个严格的`后进先出`方式来管理集合,堆栈都是最实用的模型。 下图展示了一个栈的压栈(push)/出栈(pop)的行为: @@ -161,7 +161,7 @@ swapTwoValues(&someString, &anotherString) ```swift struct IntStack { - var items = Int[]() + var items = [Int]() mutating func push(item: Int) { items.append(item) } @@ -196,10 +196,12 @@ struct Stack { `T`定义了一个名为“某种类型T”的节点提供给后来用。这种将来类型可以在结构体的定义里任何地方表示为“T”。在这种情况下,`T`在如下三个地方被用作节点: - 创建一个名为`items`的属性,使用空的T类型值数组对其进行初始化; -- 指定一个包含一个参数名为`item`的`push`方法,该参数必须是T类型; +- 指定一个包含一个参数名为`item`的`push(_:)`方法,该参数必须是T类型; - 指定一个`pop`方法的返回值,该返回值将是一个T类型值。 -当创建一个新单例并初始化时, 通过用一对紧随在类型名后的尖括号里写出实际指定栈用到类型,创建一个`Stack`实例,同创建`Array`和`Dictionary`一样: +由于`Stack`是泛型类型,所以在 Swift 中其可以用来创建任何有效类型的栈,这种方式如同`Array`和`Dictionary`。 + +你可以通过在尖括号里写出栈中需要存储的数据类型来创建并初始化一个`Stack`实例。比如,要创建一个`strings`的栈,你可以写成`Stack()`: ```swift var stackOfStrings = Stack() @@ -218,13 +220,12 @@ stackOfStrings.push("cuatro") ```swift let fromTheTop = stackOfStrings.pop() -// fromTheTop is equal to "cuatro", and the stack now contains 3 strings +// fromTheTop 等于 "cuatro", 现在栈中还有3个string ``` 下图展示了如何从栈中pop一个值的过程: ![此处输入图片的描述](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/stackPoppedOneString_2x.png) -由于`Stack`是泛型类型,所以在 Swift 中其可以用来创建任何有效类型的栈,这种方式如同`Array`和`Dictionary`。 ##类型约束 From c34a6381a44cf131db0ab9fb0cdd212a9cf25908 Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Mon, 29 Jun 2015 22:52:22 +0800 Subject: [PATCH 27/50] patterns_22:52_06/29/2015_Preliminary --- source/chapter3/07_Patterns.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 6fd48bf8..54cf38d5 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -73,7 +73,7 @@ let someValue = 42 ```swift let point = (3, 2) switch point { -// Bind x and y to the elements of point. + // Bind x and y to the elements of point. case let (x, y): print("The point is at (\(x), \(y)).") } @@ -92,7 +92,7 @@ case let (x, y): 你可以使用类型注释来限制一个元组模式来匹配某种元组类型。例如,在常量申明`let (x, y): (Int, Int) = (1, 2)`中的元组模式`(x, y): (Int, Int)`,只匹配两个元素都是`Int`这种类型的元组。如果仅需要限制一个元组模式中的某几个元素,只需要直接对这几个元素提供类型注释即可。例如,在`let (x: String, y)`中的元组模式,只要某个元组类型是包含两个元素,且第一个元素类型是`String`,则被匹配。 -当元组模式被用在`for-in`语句或者变量或常量申明时,它可以包含通配符模式,标识符模式或者其他包含这两种模式的模式。例如,下面这段代码是不正确的,因为`(x, 0)`中的元素`0`是一个表达式模式: +当元组模式被用在`for-in`语句或者变量或常量申明时,它可以包含通配符模式,标识符模式,可选模式或者其他包含这些模式的元祖模式。例如,下面这段代码是不正确的,因为`(x, 0)`中的元素`0`是一个表达式模式: ```swift let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)] @@ -204,7 +204,7 @@ default: ```swift // Overload the ~= operator to match a string with an integer func ~=(pattern: String, value: Int) -> Bool { -return pattern == "\(value)" + return pattern == "\(value)" } switch point { case ("0", "0"): From 50aa657d1b754a9d3690a24a1920509a344590ae Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Mon, 29 Jun 2015 22:54:16 +0800 Subject: [PATCH 28/50] patterns_22:54_06/29/2015_Preliminary --- source/chapter3/07_Patterns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 54cf38d5..c639a508 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -98,7 +98,7 @@ case let (x, y): let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)] // This code isn't valid. for (x, 0) in points { -/* ... */ + /* ... */ } ``` From 989e827affcb5191750ac530c50cf7c5084b9d11 Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Mon, 29 Jun 2015 23:00:18 +0800 Subject: [PATCH 29/50] patterns_23:00_06/29/2015_Preliminary --- source/chapter3/07_Patterns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index c639a508..06c6f3dd 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -19,7 +19,7 @@ swift语言中模式有2个基本的分类:一类能成功和任何值的类型相匹配,另一类在运行时(runtime)和某特定值匹配时可能会失败。 -第一类模式用于解构简单变量,常量和可选绑定中的值。此类模式包括通配符模式(wildcard pattern),标识符模式(identifier pattern),以及任何包含了它们的值绑定模式(value binding pattern)或者元祖模式(tuple pattern)。你可以为这类模式指定一个类型注释(type annotation)从而限制它们只能匹配某种特定类型的值。 +第一类模式用于解构简单变量,常量和可选绑定中的值。此类模式包括通配符模式(wildcard patterns),标识符模式(identifier patterns),以及任何包含了它们的值绑定模式(value binding patterns)或者元祖模式(tuple patterns)。你可以为这类模式指定一个类型注释(type annotation)从而限制它们只能匹配某种特定类型的值。 第二类模式用于全模式匹配,这种情况下你用来相比较的值在运行时可能还不存在。此类模式包括枚举用例模式,可选模式,表达式模式和类型转换模式。你在`switch`语句的case标签中,`do`语句的`catch`从句中,或者在`if, while, guard`和`for-in`语句的case条件句中使用这类模式。 From 7cf135d70087213fd6587b6559e6666fee2b37e5 Mon Sep 17 00:00:00 2001 From: justaway Date: Mon, 29 Jun 2015 23:05:33 +0800 Subject: [PATCH 30/50] =?UTF-8?q?=E5=B0=86'Type=20Annoation'=E7=9A=84?= =?UTF-8?q?=E7=BF=BB=E8=AF=91=E7=94=B1'=E7=B1=BB=E5=9E=8B=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3'=E6=94=B9=E4=B8=BA'=E7=B1=BB=E5=9E=8B=E6=A0=87?= =?UTF-8?q?=E6=B3=A8'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter3/02_Lexical_Structure.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/chapter3/02_Lexical_Structure.md b/source/chapter3/02_Lexical_Structure.md index 76f1ae44..3ac59140 100755 --- a/source/chapter3/02_Lexical_Structure.md +++ b/source/chapter3/02_Lexical_Structure.md @@ -89,9 +89,9 @@ Swift 的“词法结构(*lexical structure*)”描述了能构成该语言 true // 布尔型字面量 ``` -字面量本身并不包含类型信息。事实上,一个字面量会被解析为拥有无限的精度,然后 Swift 的类型推导会尝试去推导出这个字面量的类型。比如,在 `let x: Int8 = 42` 这个声明中,Swift 使用了显式类型注解(`: Int8`)来推导出 `42` 这个整型字面量的类型是 `Int8`。如果没有可用的类型信息, Swift 则会从标准库中定义的字面量类型中推导出一个默认的类型。整型字面量的默认类型是 `Int`,浮点型字面量的默认类型是 `Double`,字符串型字面量的默认类型是 `String`,布尔型字面量的默认类型是 `Bool`。比如,在 `let str = "Hello, world"` 这个声明中,字符串 `"Hello, world"`的默认推导类型就是 `String`。 +字面量本身并不包含类型信息。事实上,一个字面量会被解析为拥有无限的精度,然后 Swift 的类型推导会尝试去推导出这个字面量的类型。比如,在 `let x: Int8 = 42` 这个声明中,Swift 使用了显式类型标注(`: Int8`)来推导出 `42` 这个整型字面量的类型是 `Int8`。如果没有可用的类型信息, Swift 则会从标准库中定义的字面量类型中推导出一个默认的类型。整型字面量的默认类型是 `Int`,浮点型字面量的默认类型是 `Double`,字符串型字面量的默认类型是 `String`,布尔型字面量的默认类型是 `Bool`。比如,在 `let str = "Hello, world"` 这个声明中,字符串 `"Hello, world"`的默认推导类型就是 `String`。 -当为一个字面量值指定了类型注解的时候,这个注解的类型必须能通过这个字面量值实例化后得到。也就是说,这个类型必须遵守这些 Swift 标准库协议中的一个:整型字面量的`IntegerLiteralConvertible`协议、符点型字面量的`FloatingPointLiteralConvertible`协议、字符串字面量的`StringLiteralConvertible`协议以及布尔型字面量的`BooleanLiteralConvertible`协议。比如,`Int8` 遵守了 `IntegerLiteralConvertible`协议,因此它能在 `let x: Int8 = 42` 这个声明中作为整型字面量 `42` 的类型注解。 +当为一个字面量值指定了类型标注的时候,这个注解的类型必须能通过这个字面量值实例化后得到。也就是说,这个类型必须遵守这些 Swift 标准库协议中的一个:整型字面量的`IntegerLiteralConvertible`协议、符点型字面量的`FloatingPointLiteralConvertible`协议、字符串字面量的`StringLiteralConvertible`协议以及布尔型字面量的`BooleanLiteralConvertible`协议。比如,`Int8` 遵守了 `IntegerLiteralConvertible`协议,因此它能在 `let x: Int8 = 42` 这个声明中作为整型字面量 `42` 的类型标注。 > 字面量语法 > *字面量* → [*数字型字面量*](#numeric_literal) | [*字符串型字面量*](#string_literal) | [*布尔型字面量*](#boolean_literal) | [*nil型字面量*](#nil_literal) From 47fee2b7d510ae38c827f884f9b875e97349c630 Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Mon, 29 Jun 2015 23:29:12 +0800 Subject: [PATCH 31/50] patterns_23:29_06/29/2015_Preliminary --- source/chapter3/07_Patterns.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 06c6f3dd..9ee36996 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -11,25 +11,25 @@ - [值绑定模式(Value-Binding Pattern)](#value-binding_pattern) - [元组模式(Tuple Pattern)](#tuple_pattern) - [枚举用例模式(Enumeration Case Pattern)](#enumeration_case_pattern) -- [可选模式(Optional Patterns)](#optional_pattern) -- [类型转换模式(Type-Casting Patterns)](#type-casting_pattern) +- [可选模式(Optional Pattern)](#optional_pattern) +- [类型转换模式(Type-Casting Pattern)](#type-casting_pattern) - [表达式模式(Expression Pattern)](#expression_pattern) 模式(pattern)代表了单个值或者复合值的结构。例如,元组`(1, 2)`的结构是逗号分隔的,包含两个元素的列表。因为模式代表一种值的结构,而不是特定的某个值,你可以把模式和各种同类型的值匹配起来。比如,`(x, y)`可以匹配元组`(1, 2)`,以及任何含两个元素的元组。除了将模式与一个值匹配外,你可以从复合值中提取出部分或全部,然后分别把各个部分和一个常量或变量绑定起来。 swift语言中模式有2个基本的分类:一类能成功和任何值的类型相匹配,另一类在运行时(runtime)和某特定值匹配时可能会失败。 -第一类模式用于解构简单变量,常量和可选绑定中的值。此类模式包括通配符模式(wildcard patterns),标识符模式(identifier patterns),以及任何包含了它们的值绑定模式(value binding patterns)或者元祖模式(tuple patterns)。你可以为这类模式指定一个类型注释(type annotation)从而限制它们只能匹配某种特定类型的值。 +第一类模式用于解构简单变量,常量和可选绑定中的值。此类模式包括通配符模式(wildcard patterns),标识符模式(identifier patterns),以及任何包含了它们的值绑定模式(value binding patterns)或者元祖模式(tuple patterns)。你可以为这类模式指定一个类型标注(type annotation)从而限制它们只能匹配某种特定类型的值。 -第二类模式用于全模式匹配,这种情况下你用来相比较的值在运行时可能还不存在。此类模式包括枚举用例模式,可选模式,表达式模式和类型转换模式。你在`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) 语法 -> *模式* → [*通配符模式*](..\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#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#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#optional_pattern) [*类型注解*](..\chapter3\03_Types.html#optional_type) _可选_ +> *模式* → [*可选模式*](..\chapter3\07_Patterns.html#optional_pattern) > *模式* → [*类型转换模式*](..\chapter3\07_Patterns.html#type_casting_pattern) > *模式* → [*表达式模式*](..\chapter3\07_Patterns.html#expression_pattern) @@ -40,7 +40,7 @@ swift语言中模式有2个基本的分类:一类能成功和任何值的类 ```swift for _ in 1...3 { -// Do something three times. + // Do something three times. } ``` @@ -90,7 +90,7 @@ case let (x, y): 元组模式是逗号分隔的列表,包含一个或多个模式,并包含在一对圆括号中。元组模式匹配相应元组类型的值。 -你可以使用类型注释来限制一个元组模式来匹配某种元组类型。例如,在常量申明`let (x, y): (Int, Int) = (1, 2)`中的元组模式`(x, y): (Int, Int)`,只匹配两个元素都是`Int`这种类型的元组。如果仅需要限制一个元组模式中的某几个元素,只需要直接对这几个元素提供类型注释即可。例如,在`let (x: String, y)`中的元组模式,只要某个元组类型是包含两个元素,且第一个元素类型是`String`,则被匹配。 +你可以使用类型标注来限制一个元组模式来匹配某种元组类型。例如,在常量申明`let (x, y): (Int, Int) = (1, 2)`中的元组模式`(x, y): (Int, Int)`,只匹配两个元素都是`Int`这种类型的元组。如果仅需要限制一个元组模式中的某几个元素,只需要直接对这几个元素提供类型标注即可。例如,在`let (x: String, y)`中的元组模式,只要某个元组类型是包含两个元素,且第一个元素类型是`String`,则被匹配。 当元组模式被用在`for-in`语句或者变量或常量申明时,它可以包含通配符模式,标识符模式,可选模式或者其他包含这些模式的元祖模式。例如,下面这段代码是不正确的,因为`(x, 0)`中的元素`0`是一个表达式模式: @@ -199,7 +199,7 @@ default: // prints "(1, 2) is near the origin.” ``` -你可以重载`~=`操作符来提供自定义的表达式行为。例如,你可以重写上面的例子,以实现用字符串表达的点来比较`point`表达式。 +你可以重载`~=`操作符来提供自定义的表达式匹配行为。比如你可以重写上面的例子,拿`point`表达式去比较字符串形式的点。 ```swift // Overload the ~= operator to match a string with an integer @@ -209,8 +209,6 @@ func ~=(pattern: String, value: Int) -> Bool { switch point { case ("0", "0"): print("(0, 0) is at the origin.") -case ("-2...2", "-2...2"): - print("(\(point.0), \(point.1)) is near the origin.") default: print("The point is at (\(point.0), \(point.1)).") } From 84cae57c8b0870c99e8f9763e3ce9ca4a6f52346 Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Mon, 29 Jun 2015 23:33:12 +0800 Subject: [PATCH 32/50] patterns_23:33_06/29/2015_Preliminary --- source/chapter3/07_Patterns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index 9ee36996..d7c3313d 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -29,7 +29,7 @@ swift语言中模式有2个基本的分类:一类能成功和任何值的类 > *模式* → [*值绑定模式*](..\chapter3\07_Patterns.html#value_binding_pattern) > *模式* → [*元组模式*](..\chapter3\07_Patterns.html#tuple_pattern) [*类型标注*](..\chapter3\03_Types.html#type_annotation) _可选_ > *模式* → [*枚举用例模式*](..\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#expression_pattern) From 4f4622ea41afe0b477950ac5f4f1837d93a921e6 Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Tue, 30 Jun 2015 01:43:13 +0800 Subject: [PATCH 33/50] patterns_01:42_06/30/2015_Preliminary --- source/chapter3/07_Patterns.md | 38 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index d7c3313d..f56513a8 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -36,7 +36,7 @@ swift语言中模式有2个基本的分类:一类能成功和任何值的类 ## 通配符模式(Wildcard Pattern) -通配符模式匹配并忽略任何值,包含一个下划线(_)。当你不关心被匹配的值时,可以使用此模式。例如,下面这段代码进行了`1...3`的循环,并忽略了每次循环的值: +通配符模式由一个下划线(_)构成,且匹配并忽略任何值。当你不在乎被匹配的值时可以使用该模式。例如,下面这段代码在闭区间`1...3`中循环,每次循环时忽略该区间内的当前值: ```swift for _ in 1...3 { @@ -50,7 +50,7 @@ for _ in 1...3 { ## 标识符模式(Identifier Pattern) -标识符模式匹配任何值,并将匹配的值和一个变量或常量绑定起来。例如,在下面的常量申明中,`someValue`是一个标识符模式,匹配了类型是`Int`的`42`。 +标识符模式匹配任何值,并将匹配的值和一个变量或常量绑定起来。例如,在下面的常量声明中,`someValue`是一个标识符模式,匹配了类型是`Int`的`42`。 ```swift let someValue = 42 @@ -58,7 +58,7 @@ let someValue = 42 当匹配成功时,`42`被绑定(赋值)给常量`someValue`。 -当一个变量或常量申明的左边是标识符模式时,此时,标识符模式是隐式的值绑定模式(value-binding pattern)。 +如果一个变量或常量声明的左边的模式是一个标识符模式,那么这个标识符模式是一个隐式的值绑定模式(value-binding pattern)。 > 标识符模式语法 > *标识符模式* → [*标识符*](LexicalStructure.html#identifier) @@ -66,9 +66,9 @@ let someValue = 42 ## 值绑定模式(Value-Binding Pattern) -值绑定模式绑定匹配的值到一个变量或常量。当绑定匹配值给常量时,用关键字`let`,绑定给变量时,用关键字`var`。 +值绑定模式把匹配到的值绑定给一个变量或常量名。把绑定匹配到的值绑定给常量时,用关键字`let`,绑定给变量时,用关键字`var`。 -标识符模式包含在值绑定模式中,绑定新的变量或常量到匹配的值。例如,你可以分解一个元组的元素,并把每个元素绑定到相应的标识符模式中。 +在值绑定模式中的标识符模式会把新命名的变量或常量与匹配值做绑定。例如,你可以拆开一个元组的元素,然后把每个元素绑定到其相应一个的标识符模式中。 ```swift let point = (3, 2) @@ -80,7 +80,7 @@ case let (x, y): // prints "The point is at (3, 2).” ``` -在上面这个例子中,`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)模式语法 > *值绑定模式* → **var** [*模式*](..\chapter3\07_Patterns.html#pattern) | **let** [*模式*](..\chapter3\07_Patterns.html#pattern) @@ -88,11 +88,11 @@ case let (x, y): ## 元组模式(Tuple Pattern) -元组模式是逗号分隔的列表,包含一个或多个模式,并包含在一对圆括号中。元组模式匹配相应元组类型的值。 +元组模式是逗号分隔的,有零个或多个模式的列表,并被一对圆括号括起来。元组模式匹配相应元组类型的值。 -你可以使用类型标注来限制一个元组模式来匹配某种元组类型。例如,在常量申明`let (x, y): (Int, Int) = (1, 2)`中的元组模式`(x, y): (Int, Int)`,只匹配两个元素都是`Int`这种类型的元组。如果仅需要限制一个元组模式中的某几个元素,只需要直接对这几个元素提供类型标注即可。例如,在`let (x: String, y)`中的元组模式,只要某个元组类型是包含两个元素,且第一个元素类型是`String`,则被匹配。 +你可以使用类型标注来限制一个元组模式来匹配某些种元组类型。例如,在常量声明`let (x, y): (Int, Int) = (1, 2)`中的元组模式`(x, y): (Int, Int)`只匹配两个元素都是`Int`这种类型的元组。如果仅需要限制一个元组模式中的某几个元素,只需要直接对这几个元素提供类型标注即可。例如,在`let (x: String, y)`中的元组模式可以和任何有两个元素,且第一个元素类型是`String`的元组类型匹配。 -当元组模式被用在`for-in`语句或者变量或常量申明时,它可以包含通配符模式,标识符模式,可选模式或者其他包含这些模式的元祖模式。例如,下面这段代码是不正确的,因为`(x, 0)`中的元素`0`是一个表达式模式: +当元组模式被用在`for-in`语句或者变量或常量声明时,它仅可以包含通配符模式,标识符模式,可选模式或者其他包含这些模式的元祖模式。比如下面这段代码就不正确,因为`(x, 0)`中的元素`0`是一个表达式模式: ```swift let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)] @@ -102,7 +102,7 @@ for (x, 0) in points { } ``` -对于只包含一个元素的元组,括号是不起作用的。模式匹配那个单个元素的类型。例如,下面是等效的: +对于只包含一个元素的元组,括号是不起作用的。模式只匹配这个单个元素的类型。举例来说,下面3条语句是等效的: ```swift let a = 2 // a: Int = 2 @@ -118,7 +118,7 @@ let (a): Int = 2 // a: Int = 2 ## 枚举用例模式(Enumeration Case Pattern) -枚举用例模式匹配现有的枚举类型的某种用例。枚举用例模式仅在`switch`语句中的`case`标签中出现。 +一个枚举用例模式匹配现有的某个枚举类型的某个用例(case)。枚举用例模式出现在`switch`语句中的case标签中,以及`if`,`while`,`guard`和`for-in`语句的case条件中。 如果你准备匹配的枚举用例有任何关联的值,则相应的枚举用例模式必须指定一个包含每个关联值元素的元组模式。关于使用`switch`语句来匹配包含关联值枚举用例的例子,请参阅`Associated Values`. @@ -128,9 +128,9 @@ let (a): Int = 2 // a: Int = 2 ## 可选模式(Optional Pattern) -可选模式与封装在一个`Optional(T)`或者一个`ExplicitlyUnwrappedOptional(T)`枚举中的`Some(T)`成员值相匹配。可选模式由一个标识符模式和紧随其后的一个问号组成,在某些情况下表现为枚举用例模式。 +可选模式与封装在一个`Optional(T)`或者一个`ExplicitlyUnwrappedOptional(T)`枚举中的`Some(T)`用例相匹配。可选模式由一个标识符模式和紧随其后的一个问号组成,在某些情况下表现为枚举用例模式。 -由于可选模式是`optional`和`ImplicitlyUnwrappedOptional`枚举用例模式的语法糖(syntactic sugar),下面的两种写法一样的: +由于可选模式是`optional`和`ImplicitlyUnwrappedOptional`枚举用例模式的语法糖(syntactic sugar),下面的2种写法是一样的: ```swift let someOptional: Int? = 42 @@ -144,7 +144,7 @@ if case let x? = someOptional { print(x) } ``` -如果一个数组的元素是可选类型,可选模式为`for-in`语句提供了在该数组中迭代的简便方式,只为数组中的非空`non-nil`元素执行循环。 +如果一个数组的元素是可选类型,可选模式为`for-in`语句提供了一种在该数组中迭代的简便方式,只为数组中的非空`non-nil`元素执行循环体。 ```swift let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5] @@ -163,14 +163,14 @@ for case let number? in arrayOfOptinalInts { ## 类型转换模式(Type-Casting Patterns) -有两种类型转换模式,`is`模式和`as`模式。这两种模式均只出现在`switch`语句中的`case`标签中。`is`模式和`as`模式有以下形式: +有两种类型转换模式,`is`模式和`as`模式。这两种模式只出现在`switch`语句中的case标签中。`is`模式和`as`模式有以下形式: > is `type` > `pattern` as `type` -`is`模式匹配一个值,如果这个值的类型在运行时(runtime)和`is`模式右边的指定类型(或者那个类型的子类)是一致的。`is`模式和`is`操作符一样,它们都进行类型转换,但是抛弃了返回的类型。 +`is`模式仅当一个值的类型在运行时(runtime)和`is`模式右边的指定类型一致 - 或者是该类型的子类 - 的情况下,才会匹配这个值。`is`模式和`is`操作符有相似表现,它们都进行类型转换,却舍弃返回的类型。 -`as`模式匹配一个值,如果这个值的类型在运行时(runtime)和`as`模式右边的指定类型(或者那个类型的子类)是一致的。一旦匹配成功,匹配的值的类型被转换成`as`模式左边指定的模式。 +`as`模式仅当一个值的类型在运行时(runtime)和`as`模式右边的指定类型一致 - 或者是该类型的子类 - 的情况下,才会匹配这个值。如果匹配成功,被匹配的值的类型被转换成`as`模式左边指定的模式。 关于使用`switch`语句来匹配`is`模式和`as`模式值的例子,请参阅`Type Casting for Any and AnyObject`。 @@ -182,9 +182,9 @@ for case let number? in arrayOfOptinalInts { ## 表达式模式(Expression Pattern) -表达式模式代表了一个表达式的值。这个模式只出现在`switch`语句中的`case`标签中。 +一个表达式模式代表了一个表达式的值。表达式模式只出现在`switch`语句中的`case`标签中。 -由表达式模式所代表的表达式用Swift标准库中的`~=`操作符与输入表达式的值进行比较。如果`~=`操作符返回`true`,则匹配成功。默认情况下,`~=`操作符使用`==`操作符来比较两个相同类型的值。它也可以匹配一个整数值与一个`Range`对象中的整数范围,正如下面这个例子所示: +由表达式模式所代表的表达式与使用了Swift标准库中`~=`操作符的输入表达式的值进行比较。如果`~=`操作符返回`true`,则匹配成功。默认情况下,`~=`操作符使用`==`操作符来比较两个相同类型的值。它也可以将一个整型数值与一个`Range`对象中的一段整数区间做匹配,正如下面这个例子所示: ```swift let point = (1, 2) From 93186d21113d21e6a1d89410c96e02d61e8e7633 Mon Sep 17 00:00:00 2001 From: ray16897188 Date: Tue, 30 Jun 2015 01:46:46 +0800 Subject: [PATCH 34/50] patterns_01:46_06/30/2015_Preliminary --- source/chapter3/07_Patterns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/chapter3/07_Patterns.md b/source/chapter3/07_Patterns.md index f56513a8..fb93956d 100755 --- a/source/chapter3/07_Patterns.md +++ b/source/chapter3/07_Patterns.md @@ -90,7 +90,7 @@ case let (x, y): 元组模式是逗号分隔的,有零个或多个模式的列表,并被一对圆括号括起来。元组模式匹配相应元组类型的值。 -你可以使用类型标注来限制一个元组模式来匹配某些种元组类型。例如,在常量声明`let (x, y): (Int, Int) = (1, 2)`中的元组模式`(x, y): (Int, Int)`只匹配两个元素都是`Int`这种类型的元组。如果仅需要限制一个元组模式中的某几个元素,只需要直接对这几个元素提供类型标注即可。例如,在`let (x: String, y)`中的元组模式可以和任何有两个元素,且第一个元素类型是`String`的元组类型匹配。 +你可以使用类型标注去限制一个元组模式能匹配哪些种元组类型。例如,在常量声明`let (x, y): (Int, Int) = (1, 2)`中的元组模式`(x, y): (Int, Int)`只匹配两个元素都是`Int`这种类型的元组。如果仅需要限制一个元组模式中的某几个元素,只需要直接对这几个元素提供类型标注即可。例如,在`let (x: String, y)`中的元组模式可以和任何有两个元素,且第一个元素类型是`String`的元组类型匹配。 当元组模式被用在`for-in`语句或者变量或常量声明时,它仅可以包含通配符模式,标识符模式,可选模式或者其他包含这些模式的元祖模式。比如下面这段代码就不正确,因为`(x, 0)`中的元素`0`是一个表达式模式: From a84a65fd553a64a7371668b66d6109d97d22ad7f Mon Sep 17 00:00:00 2001 From: Cai Yi Date: Tue, 30 Jun 2015 10:52:06 +0800 Subject: [PATCH 35/50] Update 08_Generic_Parameters_and_Arguments.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 翻译swift2.0版本的泛型参数章节,对之前版本进行校验 --- .../08_Generic_Parameters_and_Arguments.md | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/source/chapter3/08_Generic_Parameters_and_Arguments.md b/source/chapter3/08_Generic_Parameters_and_Arguments.md index 06a078b0..9bb891a4 100755 --- a/source/chapter3/08_Generic_Parameters_and_Arguments.md +++ b/source/chapter3/08_Generic_Parameters_and_Arguments.md @@ -1,5 +1,5 @@ > 翻译:[fd5788](https://github.com/fd5788) -> 校对:[yankuangshi](https://github.com/yankuangshi), [stanzhai](https://github.com/stanzhai) +> 校对:[yankuangshi](https://github.com/yankuangshi), [stanzhai](https://github.com/stanzhai), [wardenNScaiyi](https:github.com/wardenNScaiyi) # 泛型参数 --------- @@ -9,28 +9,29 @@ - [泛型形参子句](#generic_parameter) - [泛型实参子句](#generic_argument) -本节涉及泛型类型、泛型函数以及泛型构造器的参数,包括形参和实参。声明泛型类型、函数或构造器时,须指定相应的类型参数。类型参数相当于一个占位符,当实例化泛型类型、调用泛型函数或泛型构造器时,就用具体的类型实参替代之。 +本节涉及泛型类型、泛型函数以及泛型初始化器(**initializer**)的参数,包括形参和实参。声明泛型类型、函数或初始化器时,须指定相应的类型参数。类型参数相当于一个占位符,当实例化泛型类型、调用泛型函数或泛型初始化器时,就用具体的类型实参替代之。 关于 Swift 语言的泛型概述,见[泛型](../charpter2/22_Generics.md)(第二部分第22章)。 ## 泛型形参子句 -泛型形参子句指定泛型类型或函数的类型形参,以及这些参数的关联约束和要求。泛型形参子句用尖括号(<>)包住,并且有以下两种形式: +泛型形参子句指定泛型类型或函数的类型形参,以及这些参数的关联约束和关联类型要求(**requirement**)。泛型形参子句用尖括号(<>)包住,并且有以下两种形式: -> <`generic parameter list`> -> <`generic parameter list` where `requirements`> +> <`泛型形参列表`> +> <`泛型形参列表` where `关联类型要求`> -泛型形参列表中泛型形参用逗号分开,每一个采用以下形式: +泛型形参列表中泛型形参用逗号分开,其中每一个采用以下形式: -> `type parameter` : `constrain` +> `类型形参` : `约束` -泛型形参由两部分组成:类型形参及其后的可选约束。类型形参只是占位符类型(如T,U,V,KeyType,ValueType等)的名字而已。你可以在泛型类型、函数的其余部分或者构造器声明,以及函数或构造器的签名中使用它。 +泛型形参由两部分组成:类型形参及其后的可选约束。类型形参只是占位符类型(如 T,U,V,Key,Value 等)的名字而已。你可以在泛型类型、函数的其余部分或者初始化器声明,包括函数或初始化器的签名中使用它(与其任何相关类型)。 + +约束用于指明该类型形参继承自某个类或者遵守某个协议或协议的一部分。例如,在下面的泛型函数中,泛型形参`T: Comparable`表示任何用于替代类型形参`T`的类型实参必须满足`Comparable`协议。 -约束用于指明该类型形参继承自某个类或者遵守某个协议或协议的一部分。例如,在下面的泛型中,泛型形参`T: Comparable`表示任何用于替代类型形参`T`的类型实参必须满足`Comparable`协议。 ```swift -func simpleMin(x: T, y: T) -> T { +func simpleMax(x: T, _ y: T) -> T { if x < y { return y } @@ -38,28 +39,30 @@ func simpleMin(x: T, y: T) -> T { } ``` -如,`Int`和`Double`均满足`Comparable`协议,该函数接受任何一种类型。与泛型类型相反,调用泛型函数或构造器时不需要指定泛型实参子句。类型实参由传递给函数或构造器的实参推断而出。 -```swift -simpleMin(17, 42) // T is inferred to be Int -simpleMin(3.14159, 2.71828) // T is inferred to be Double + +如,`Int`和`Double`均满足`Comparable`协议,该函数接受任何一种类型。与泛型类型相反,调用泛型函数或初始化器时不需要指定泛型实参子句。类型实参由传递给函数或初始化器的实参推断而出。 + + +``` +simpleMax(17, 42) // T被推断出为Int类型 +simpleMax(3.14159, 2.71828) // T被推断出为Double类型 ``` ## Where 子句 -要想对类型形参及其关联类型指定额外要求,可以在泛型形参列表之后添加`where`子句。`where`子句由关键字`where`及其后的用逗号分割的多个要求组成。 +要想对类型形参及其关联类型指定额外关联类型要求,可以在泛型形参列表之后添加`where`子句。`where`子句由关键字`where`及其后的用逗号分割的多个关联类型要求组成。 -`where`子句中的要求用于指明该类型形参继承自某个类或遵守某个协议或协议的一部分。尽管`where`子句有助于表达类型形参上的简单约束(如`T: Comparable`等同于`T where T: Comparable`,等等),但是依然可以用来对类型形参及其关联约束提供更复杂的约束。如,``表示泛型类型`T`继承自类`C`且遵守协议`P`。 +`where`子句中的关联关系用于指明该类型形参继承自某个类或遵守某个协议或协议的一部分。尽管`where`子句提供了语法糖使其有助于表达类型形参上的简单约束(如`T: Comparable`等同于`T where T: Comparable`,等等),但是依然可以用来对类型形参及其关联类型提供更复杂的约束。如,``表示泛型类型`T`继承自类`C`且遵守协议`P`。 -如上所述,可以强制约束类型形参的关联类型遵守某个协议。``表示`T`遵守`Generator`协议,而且`T`的关联类型`T.Element`遵守`Eauatable`协议(`T`有关联类型是因为`Generator`声明了`Element`,而`T`遵守`Generator`协议)。 +如上所述,可以强制约束类型形参的关联类型遵守某个协议。例如``表示`T`遵守`Generator`协议,而且`T`的关联类型`T.Element`遵守`Eauatable`协议(`T`有关联类型`Element`是因为`Generator`声明了`Element`,而`T`遵守`Generator`协议)。 -也可以用操作符`==`来指定两个类型等效的要求。例如,有这样一个约束:`T`和`U`遵守`Generator`协议,同时要求它们的关联类型等同,可以这样来表达:``。 +也可以用操作符`==`来指定两个类型等效的关联关系。例如,有这样一个约束:`T`和`U`遵守`Generator`协议,同时要求它们的关联类型等同,可以这样来表达:``。 -当然,替代类型形参的类型实参必须满足所有类型形参所要求的约束和要求。 +当然,替代类型形参的类型实参必须满足所有类型形参的约束和关联类型要求。 -泛型函数或构造器可以重载,但在泛型形参子句中的类型形参必须有不同的约束或要求,抑或二者皆不同。当调用重载的泛型函数或构造器时,编译器会用这些约束来决定调用哪个重载函数或构造器。 +泛型函数或初始化器可以重载,但在泛型形参子句中的类型形参必须有不同的约束或关联类型要求,抑或二者皆不同。当调用重载的泛型函数或始化器时,编译器会用这些约束来决定调用哪个重载函数或始化器。 -泛型类可以生成一个子类,但是这个子类也必须是泛型类。 > 泛型形参子句语法 > *泛型参数子句* → **<** [*泛型参数列表*](GenericParametersAndArguments.html#generic_parameter_list) [*约束子句*](GenericParametersAndArguments.html#requirement_clause) _可选_ **>** @@ -80,27 +83,30 @@ simpleMin(3.14159, 2.71828) // T is inferred to be Double 泛型实参子句指定_泛型类型_的类型实参。泛型实参子句用尖括号(<>)包住,形式如下: -> <`generic argument list`> +> <`泛型实参列表`> 泛型实参列表中类型实参有逗号分开。类型实参是实际具体类型的名字,用来替代泛型类型的泛型形参子句中的相应的类型形参。从而得到泛型类型的一个特化版本。如,Swift标准库的泛型字典类型定义如下: + ```swift struct Dictionary: Collection, DictionaryLiteralConvertible { + /* .. */ + } ``` -泛型`Dictionary`类型的特化版本,`Dictionary`就是用具体的`String`和`Int`类型替代泛型类型`KeyType: Hashable`和`ValueType`产生的。每一个类型实参必须满足它所替代的泛型形参的所有约束,包括任何`where`子句所指定的额外的要求。上面的例子中,类型形参`KeyType`要求满足`Hashable`协议,因此`String`也必须满足`Hashable`协议。 +泛型`Dictionary`类型的特化版本,`Dictionary`就是用具体的`String`和`Int`类型替代泛型类型`KeyType: Hashable`和`ValueType`产生的。每一个类型实参必须满足它所替代的泛型形参的所有约束,包括任何`where`子句所指定的额外的关联类型要求。上面的例子中,类型形参`Key`类型要求满足`Hashable`协议,因此`String`也必须满足`Hashable`协议。 -可以用本身就是泛型类型的特化版本的类型实参替代类型形参(假设已满足合适的约束和要求)。例如,为了生成一个元素类型是整型数组的数组,可以用数组的特化版本`Array`替代泛型类型`Array`的类型形参`T`来实现。 +可以用本身就是泛型类型的特化版本的类型实参替代类型形参(假设已满足合适的约束和关联类型要求)。例如,为了生成一个元素类型是整型数组的数组,可以用数组的特化版本`Array`替代泛型类型`Array`的类型形参 `T` 来实现。 -```swift +``` let arrayOfArrays: Array> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] ``` -如[泛型形参子句](#generic_parameter)所述,不能用泛型实参子句来指定泛型函数或构造器的类型实参。 +如[泛型形参子句](#generic_parameter)所述,不能用泛型实参子句来指定泛型函数或初始化器的类型实参。 > 泛型实参子句语法 > *(泛型参数子句Generic Argument Clause)* → **<** [*泛型参数列表*](GenericParametersAndArguments.html#generic_argument_list) **>** > *泛型参数列表* → [*泛型参数*](GenericParametersAndArguments.html#generic_argument) | [*泛型参数*](GenericParametersAndArguments.html#generic_argument) **,** [*泛型参数列表*](GenericParametersAndArguments.html#generic_argument_list) -> *泛型参数* → [*类型*](..\chapter3\03_Types.html#type) \ No newline at end of file +> *泛型参数* → [*类型*](..\chapter3\03_Types.html#type) From 59faefec310c75f2e2f0c5f7e7a592494d7f8f1e Mon Sep 17 00:00:00 2001 From: Perry Date: Tue, 30 Jun 2015 15:38:09 +0800 Subject: [PATCH 36/50] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=A4=E6=AE=B5?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=AD=A3=E9=83=A8=E5=88=86=E6=96=87=E6=A1=88?= =?UTF-8?q?=E7=BB=86=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/24_Access_Control.md | 125 ++++++++++++++++----------- 1 file changed, 74 insertions(+), 51 deletions(-) diff --git a/source/chapter2/24_Access_Control.md b/source/chapter2/24_Access_Control.md index f2094f60..fa4e21b2 100644 --- a/source/chapter2/24_Access_Control.md +++ b/source/chapter2/24_Access_Control.md @@ -12,6 +12,7 @@ - [默认访问级别](#default_access_levels) - [单目标应用程序的访问级别](#access_levels_for_single-target_apps) - [Framework的访问级别](#access_levels_for_frameworks) + - [单元测试目标的访问级别](#access_levels_for_unit_test_targets) - [访问控制语法](#access_control_syntax) - [自定义类型](#custom_types) - [元组类型](#tuple_types) @@ -33,45 +34,47 @@ - [泛型](#generics) - [类型别名](#type_aliases) -访问控制可以限定你在源文件或模块中访问代码的级别,也就是说可以控制哪些代码你可以访问,哪些代码你不能访问。这个特性可以让我们隐藏功能实现的一些细节,并且可以明确的指定我们提供给其他人的接口中哪些部分是他们可以使用的,哪些是他们看不到的。 +*访问控制*可以限定其他源文件或模块中代码对你代码的访问级别。这个特性可以让我们隐藏功能实现的一些细节,并且可以明确的申明我们提供给其他人的接口中哪些部分是他们可以访问和使用的。 -你可以明确的给类、结构体、枚举、设置访问级别,也可以给属性、函数、初始化方法、基本类型、下标索引等设置访问级别。协议也可以被限定在一定的范围内使用,包括协议里的全局常量、变量和函数。 +你可以明确地给单个类型(类、结构体、枚举)设置访问级别,也可以给这些类型的属性、函数、初始化方法、基本类型、下标索引等设置访问级别。协议也可以被限定在一定的范围内使用,包括协议里的全局常量、变量和函数。 -在提供了不同访问级别的同时,Swift 并没有规定我们要在任何时候都要在代码中明确指定访问级别。其实,如果我们作为独立开发者在开发我们自己的 app,而不是在开发一些`Framework`的时候,我们完全可以不用明确的指定代码的访问级别。 +在提供了不同访问级别的同时,Swift还为某些典型场景提供了默认的访问级别,这样就不需要我们在每段代码中都申明显式访问级别。其实,如果只是开发一个单目标应用程序,我们完全可以不用申明代码的显式访问级别。 -> 注意:为方便起见,在代码中可以设置访问级别的它们(属性、基本类型、函数等)在下面的章节中我们称之为“实体”。 +> 注意:简单起见,代码中可以设置访问级别的特性(属性、基本类型、函数等),在下面的章节中我们会以“实体”代替。 ## 模块和源文件 Swift 中的访问控制模型基于模块和源文件这两个概念。 -模块指的是`Framework`或`App bundle`。在 Swift 中,可以用`import`关键字引入自己的工程。 +*模块*指的是以独立单元构建和发布的`Framework`或`Application`。在Swift 中的一个模块可以使用`import`关键字引入另外一个模块。 -在 Swift 中,`Framework`或`App bundle`被作为模块处理。如果你是为了实现某个通用的功能,或者是为了封装一些常用方法而将代码打包成`Framework`,这个`Framework`在 Swift 中就被称为模块。不论它被引入到某个 App 工程或者其他的`Framework`,它里面的一切(属性、函数等)都属于这个模块。 +在 Swift 中,Xcode的每个构建目标(比如`Framework`或`app bundle`)都被当作模块处理。如果你是为了实现某个通用的功能,或者是为了封装一些常用方法而将代码打包成独立的`Framework`,这个`Framework`在 Swift 中就被称为模块。当它被引入到某个 app 工程或者另外一个`Framework`时,它里面的一切(属性、函数等)仍然属于这个独立的模块。 -源文件指的是 Swift 中的`Swift File`,就是编写 Swift 代码的文件,它通常属于一个模块。通常一个源文件包含一个`类`,在`类`中又包含`函数`、`属性`等类型。 +*源文件*指的是 Swift 中的`Swift File`,就是编写 Swift 源代码的文件,它通常属于一个模块。尽管一般我们将不同的`类` 分别定义在不同的源文件中,但是同一个源文件可以包含多个`类`和`函数` 的定义。 ## 访问级别 -Swift 提供了三种不同的访问级别。这些访问级别相对于源文件中定义的实体,同时也相对于这些源文件所属的模块。 +Swift 为代码中的实体提供了三种不同的访问级别。这些访问级别不仅与源文件中定义的实体相关,同时也与源文件所属的模块相关。 -- `Public`:可以访问自己模块或应用中源文件里的任何实体,别人也可以访问引入该模块中源文件里的所有实体。通常情况下,某个接口或`Framework`是可以被任何人使用时,你可以将其设置为`public`级别。 -- `Internal`:可以访问自己模块或应用中源文件里的任何实体,但是别人不能访问该模块中源文件里的实体。通常情况下,某个接口或`Framework`作为内部结构使用时,你可以将其设置为`internal`级别。 -- `Private`:只能在当前源文件中使用的实体,称为私有实体。使用`private`级别,可以用作隐藏某些功能的实现细节。 +- `public`:可以访问自己模块中源文件里的任何实体,别人也可以通过引入该模块来访问源文件里的所有实体。通常情况下,`Framework` 中的某个接口是可以被任何人使用时,你可以将其设置为`public`级别。 +- `internal`:可以访问自己模块中源文件里的任何实体,但是别人不能访问该模块中源文件里的实体。通常情况下,某个接口或`Framework`作为内部结构使用时,你可以将其设置为`internal`级别。 +- `private`:只能在当前源文件中使用的实体,称为私有实体。使用`private`级别,可以用作隐藏某些功能的实现细节。 -`Public`为最高级访问级别,`Private`为最低级访问级别。 +`public`为最高级访问级别,`private`为最低级访问级别。 + +> 注意:Swift中的`private`访问和其他语言中的`private`访问不太一样,它的范围限于整个源文件,而不是声明。这就意味着,一个`类` 可以访问定义该`类` 的源文件中定义的所有`private`实体,但是如果一个`类` 的扩展是定义在独立的源文件中,那么就不能访问这个`类` 的`private`成员。 ### 访问级别的使用原则 -在 Swift 中,访问级别有如下使用原则:访问级别统一性。 +Swift 中的访问级别遵循一个使用原则:访问级别统一性。 比如说: -- 一个`public`访问级别的变量,不能将它的类型定义为`internal`和`private`的类型。因为变量可以被任何人访问,但是定义它的类型不可以,所以这样就会出现错误。 -- 函数的访问级别不能高于它的参数、返回类型的访问级别。因为如果函数定义为`public`而参数或者返回类型定义为`internal`或`private`,就会出现函数可以被任何人访问,但是它的参数和返回类型不可以,同样会出现错误。 +- 一个`public`访问级别的变量,不能将它的类型定义为`internal`和`private`。因为变量可以被任何人访问,但是定义它的类型不可以,所以这样就会出现错误。 +- 函数的访问级别不能高于它的参数、返回类型的访问级别。因为如果函数定义为`public`而参数或者返回类型定义为`internal`或`private`,就会出现函数可以被任何人访问,但是它的参数和返回类型确不可以,同样会出现错误。 ### 默认访问级别 -代码中的所有实体,如果你不明确的定义其访问级别,那么它们默认为`internal`级别。在大多数情况下,我们不需要明确的设置实体的访问级别,因为我们大多数时候都是在开发一个 App bundle。 +如果你不为代码中的所有实体定义显式访问级别,那么它们默认为`internal`级别。在大多数情况下,我们不需要设置实体的显式访问级别。因为我们一般都是在开发一个`app bundle`。 ### 单目标应用程序的访问级别 @@ -79,9 +82,14 @@ Swift 提供了三种不同的访问级别。这些访问级别相对于源文 ### Framework的访问级别 -当你开发`Framework`时,就需要把一些实体定义为`public`级别,以便其他人导入该`Framework`后可以正常使用其功能。这些被你定义为`public`的实体,就是这个`Framework`的API。 +当你开发`Framework`时,就需要把一些对外的接口定义为`public`级别,以便其他人导入该`Framework`后可以正常使用其功能。这些被你定义为`public`的接口,就是这个`Framework`的API。 -> 注意:`Framework`的内部实现细节依然可以使用默认的`internal`级别,或者也可以定义为`private`级别。只有你想将它作为 API 的实体,才将其定义为`public`级别。 +> 注意:`Framework`的内部实现细节依然可以使用默认的`internal`级别,或者也可以定义为`private`级别。只有当你想把它作为 API 的一部分的时候,才将其定义为`public`级别。 + + +### 单元测试目标的访问级别 + +当你的app有单元测试目标时,为了方便测试,测试模块需要能访问到你app中的代码。默认情况下只有`public`级别的实体才可以被其他模块访问。然而,如果在引入一个生产模块时使用`@testable`注解,然后用带测试的方式编译这个生产模块,单元测试目标就可以访问所有`internal`级别的实体。 ## 访问控制语法 @@ -97,7 +105,7 @@ internal let someInternalConstant = 0 private func somePrivateFunction() {} ``` -除非有特殊的说明,否则实体都使用默认的访问级别`internal`,可以查阅**默认访问级别**这一节。这意味着`SomeInternalClass`和`someInternalConstant`不用明确的使用修饰符声明访问级别,但是他们任然拥有隐式的访问级别`internal`: +除非有特殊的说明,否则实体都使用默认的访问级别`internal`,可以查阅**[默认访问级别](#default_access_levels)**这一节。这意味着在不使用修饰符声明显式访问级别的情况下,`SomeInternalClass`和`someInternalConstant`仍然拥有隐式的访问级别`internal`: ```swift class SomeInternalClass {} // 隐式访问级别 internal @@ -105,40 +113,40 @@ var someInternalConstant = 0 // 隐式访问级别 internal ``` ## 自定义类型 -如果你想为一个自定义类型指定一个明确的访问级别,那么你要明确一点。那就是你要确保新类型的访问级别和它实际的作用域相匹配。比如说,如果某个类里的属性、函数、返回值它们的作用域仅在当前的源文件中,那么你就可以将这个类申明为`private`类,而不需要申明为`public`或者`internal`类。 +如果想为一个自定义类型申明显式访问级别,那么要明确一点。那就是你要确保新类型的访问级别和它实际的作用域相匹配。比如说,如果你定义了一个`private`类,那这个类就只能在定义它的源文件中当作属性类型、函数参数或者返回类型使用。 -类的访问级别也可以影响到类成员(属性、函数、初始化方法等)的默认访问级别。如果你将类申明为`private`类,那么该类的所有成员的默认访问级别也会成为`private`。如果你将类申明为`public`或者`internal`类(或者不明确的指定访问级别,而使用默认的`internal`访问级别),那么该类的所有成员的访问级别是`internal`。 +类的访问级别也可以影响到类成员(属性、函数、初始化方法等)的默认访问级别。如果你将类申明为`private`类,那么该类的所有成员的默认访问级别也会成为`private`。如果你将类申明为`public`或者`internal`类(或者不明确的申明访问级别,而使用默认的`internal`访问级别),那么该类的所有成员的访问级别是`internal`。 -> 注意:上面提到,一个`public`类的所有成员的访问级别默认为`internal`级别,而不是`public`级别。如果你想将某个成员申明为`public`级别,那么你必须使用修饰符明确的申明该成员。这样做的好处是,在你定义公共接口API的时候,可以明确的选择哪些属性或方法是需要公开的,哪些是内部使用的,可以避免将内部使用的属性方法公开成公共API的错误。 +> 注意:上面提到,一个`public`类的所有成员的访问级别默认为`internal`级别,而不是`public`级别。如果你想将某个成员申明为`public`级别,那么你必须使用修饰符明确的声明该成员。这样做的好处是,在你定义公共接口API的时候,可以明确的选择哪些属性或方法是需要公开的,哪些是内部使用的,可以避免将内部使用的属性方法公开成公共API的错误。 ```swift -public class SomePublicClass { // 显示的 public 类 - public var somePublicProperty = 0 // 显示的 public 类成员 +public class SomePublicClass { // 显式的 public 类 + public var somePublicProperty = 0 // 显式的 public 类成员 var someInternalProperty = 0 // 隐式的 internal 类成员 - private func somePrivateMethod() {} // 显示的 private 类成员 + private func somePrivateMethod() {} // 显式的 private 类成员 } class SomeInternalClass { // 隐式的 internal 类 var someInternalProperty = 0 // 隐式的 internal 类成员 - private func somePrivateMethod() {} // 显示的 private 类成员 + private func somePrivateMethod() {} // 显式的 private 类成员 } -private class SomePrivateClass { // 显示的 private 类 +private class SomePrivateClass { // 显式的 private 类 var somePrivateProperty = 0 // 隐式的 private 类成员 func somePrivateMethod() {} // 隐式的 private 类成员 } ``` ### 元组类型 -元组的访问级别使用是所有类型的访问级别使用中最为严谨的。比如说,如果你构建一个包含两种不同类型元素的元组,其中一个元素类型的访问级别为`internal`,另一个为`private`级别,那么这个元组的访问级别为`private`。也就是说元组的访问级别遵循它里面元组中最低级的访问级别。 +元组的访问级别使用是所有类型的访问级别使用中最为严谨的。比如说,如果你构建一个包含两种不同类型元素的元组,其中一个元素类型的访问级别为`internal`,另一个为`private`级别,那么这个元组的访问级别为`private`。也就是说元组的访问级别与元组中访问级别最低的类型一致。 > 注意:元组不同于类、结构体、枚举、函数那样有单独的定义。元组的访问级别是在它被使用时自动推导出的,而不是明确的申明。 ### 函数类型 -函数的访问级别需要根据该函数的参数类型访问级别、返回类型访问级别得出。如果根据参数类型和返回类型得出的函数访问级别不符合上下文,那么就需要明确的申明该函数的访问级别。 +函数的访问级别需要根据该函数的参数类型和返回类型的访问级别得出。如果根据参数类型和返回类型得出的函数访问级别不符合默认上下文,那么就需要明确地申明该函数的访问级别。 -下面的例子中定义了一个全局函数名为`someFunction`,并且没有明确的申明其访问级别。你也许会认为该函数应该拥有默认的访问级别`internal`,但事实并非如此。事实上,如果按下面这种写法,编译器是无法编译通过的: +下面的例子定义了一个名为`someFunction`全局函数,并且没有明确地申明其访问级别。也许你会认为该函数应该拥有默认的访问级别`internal`,但事实并非如此。事实上,如果按下面这种写法,带埋是无法编译通过的: ```swift func someFunction() -> (SomeInternalClass, SomePrivateClass) { @@ -146,9 +154,9 @@ func someFunction() -> (SomeInternalClass, SomePrivateClass) { } ``` -我们可以看到,这个函数的返回类型是一个元组,该元组中包含两个自定义的类(可查阅**自定义类型**)。其中一个类的访问级别是`internal`,另一个的访问级别是`private`,所以根据元组访问级别的原则,该元组的访问级别是`private`(元组的访问级别遵循它里面元组中最低级的访问级别)。 +我们可以看到,这个函数的返回类型是一个元组,该元组中包含两个自定义的类(可查阅**[自定义类型](#custom_types)**)。其中一个类的访问级别是`internal`,另一个的访问级别是`private`,所以根据元组访问级别的原则,该元组的访问级别是`private`(元组的访问级别与元组中访问级别最低的类型一致)。 -因为该函数返回类型的访问级别是`private`,所以你必须使用`private`修饰符,明确的申请该函数: +因为该函数返回类型的访问级别是`private`,所以你必须使用`private`修饰符,明确的声明该函数: ```swift private func someFunction() -> (SomeInternalClass, SomePrivateClass) { @@ -160,7 +168,7 @@ private func someFunction() -> (SomeInternalClass, SomePrivateClass) { ### 枚举类型 -枚举中成员的访问级别继承自该枚举,你不能为枚举中的成员指定访问级别。 +枚举中成员的访问级别继承自该枚举,你不能为枚举中的成员单独申明不同的访问级别。 比如下面的例子,枚举`CompassPoint`被明确的申明为`public`级别,那么它的成员`North`,`South`,`East`,`West`的访问级别同样也是`public`: @@ -175,11 +183,11 @@ public enum CompassPoint { ### 原始值和关联值 -用于枚举定义中的任何原始值,或关联的值类型必须有一个访问级别,至少要高于枚举的访问级别。比如说,你不能在一个`internal`访问级别的枚举中定义`private`级别的原始值类型。 +枚举定义中的任何原始值或关联值的类型都必须有一个访问级别,这个级别至少要不低于枚举的访问级别。比如说,你不能在一个`internal`访问级别的枚举中定义`private`级别的原始值类型。 ### 嵌套类型 -如果在`private`级别的类型中定义嵌套类型,那么该嵌套类型就自动拥有`private`访问级别。如果在`public`或者`internal`级别的类型中定义嵌套类型,那么该嵌套类型自动拥有`internal`访问级别。如果想让嵌套类型拥有`public`访问级别,那么需要对该嵌套类型进行明确的访问级别申明。 +如果在`private`级别的类型中定义嵌套类型,那么该嵌套类型就自动拥有`private`访问级别。如果在`public`或者`internal`级别的类型中定义嵌套类型,那么该嵌套类型自动拥有`internal`访问级别。如果想让嵌套类型拥有`public`访问级别,那么需要明确地申明该嵌套类型的访问级别。 ## 子类 @@ -217,7 +225,7 @@ internal class B: A { ## 常量、变量、属性、下标 -常量、变量、属性不能拥有比它们的类型更高的访问级别。比如说,你定义一个`public`级别的属性,但是它的类型是`private`级别的,这是编译器不允许的。同样,下标也不能拥有比索引类型或返回类型更高的访问级别。 +常量、变量、属性不能拥有比它们的类型更高的访问级别。比如说,你定义一个`public`级别的属性,但是它的类型是`private`级别的,这是编译器所不允许的。同样,下标也不能拥有比索引类型或返回类型更高的访问级别。 如果常量、变量、属性、下标索引的定义类型是`private`级别的,那么它们必须要明确的申明访问级别为`private`: @@ -229,11 +237,11 @@ private var privateInstance = SomePrivateClass() ### Getter和Setter 常量、变量、属性、下标索引的`Getters`和`Setters`的访问级别继承自它们所属成员的访问级别。 -`Setter`的访问级别可以低于对应的`Getter`的访问级别,这样就可以控制变量、属性或下标索引的读写权限。在`var`或`subscript`定义作用域之前,你可以通过`private(set)`或`internal(set)`先为它门的写权限申明一个较低的访问级别。 +`Setter`的访问级别可以低于对应的`Getter`的访问级别,这样就可以控制变量、属性或下标索引的读写权限。在`var`或`subscript`定义作用域之前,你可以通过`private(set)`或`internal(set)`先为它们的写权限申明一个较低的访问级别。 -> 注意:这个规定适用于用作存储的属性或用作计算的属性。即使你不明确的申明存储属性的`Getter`、`Setter`,Swift也会隐式的为其创建`Getter`和`Setter`,用于对该属性进行读取操作。使用`private(set)`和`internal(set)`可以改变Swift隐式创建的`Setter`的访问级别。在计算属性中也是同样的。 +> 注意:这个规定适用于用作存储的属性或用作计算的属性。即使你不明确地申明存储属性的`Getter`、`Setter`,Swift也会隐式的为其创建`Getter`和`Setter`,用于对该属性进行读取操作。使用`private(set)`和`internal(set)`可以改变Swift隐式创建的`Setter`的访问级别。这对计算属性也同样适用。 -下面的例子中定义了一个结构体名为`TrackedString`,它记录了`value`属性被修改的次数: +下面的例子中定义了一个名为`TrackedString`的结构体,它记录了`value`属性被修改的次数: ```swift struct TrackedString { @@ -247,11 +255,11 @@ struct TrackedString { ``` -`TrackedString`结构体定义了一个用于存储的属性名为`value`,类型为`String`,并将初始化值设为`""`(即一个空字符串)。该结构体同时也定义了另一个用于存储的属性名为`numberOfEdits`,类型为`Int`,它用于记录属性`value`被修改的次数。这个功能的实现通过属性`value`的`didSet`方法实现,每当给`value`赋新值时就会调用`didSet`方法,给`numberOfEdits`加一。 +`TrackedString`结构体定义了一个用于存储`String`类型的属性`value`,并将初始化值设为`""`(即一个空字符串)。该结构体同时也定义了另一个用于存储`Int`类型的属性名`numberOfEdits`,它用于记录属性`value`被修改的次数。这个功能的实现通过属性`value`的`didSet`方法实现,每当给`value`赋新值时就会调用`didSet`方法,然后将`numberOfEdits`的值加一。 -结构体`TrackedString`和它的属性`value`均没有明确的申明访问级别,所以它们都拥有默认的访问级别`internal`。但是该结构体的`numberOfEdits`属性使用`private(set)`修饰符进行申明,这意味着`numberOfEdits`属性只能在定义该结构体的源文件中赋值。`numberOfEdits`属性的`Getter`依然是默认的访问级别`internal`,但是`Setter`的访问级别是`private`,这表示该属性只有在当前的源文件中是可读可写的,在当前源文件所属的模块中它只是一个可读的属性。 +结构体`TrackedString`和它的属性`value`均没有申明显式访问级别,所以它们都拥有默认的访问级别`internal`。但是该结构体的`numberOfEdits`属性使用`private(set)`修饰符进行申明,这意味着`numberOfEdits`属性只能在定义该结构体的源文件中赋值。`numberOfEdits`属性的`Getter`依然是默认的访问级别`internal`,但是`Setter`的访问级别是`private`,这表示该属性只有在当前的源文件中是可读写的,而在当前源文件所属的模块中它只是一个可读的属性。 -如果你实例化`TrackedString`结构体,并且多次对`value`属性的值进行修改,你就会看到`numberOfEdits`的值会随着修改次数更改: +如果你实例化`TrackedString`结构体,并且多次对`value`属性的值进行修改,你就会看到`numberOfEdits`的值会随着修改次数进行变化: ```swift var stringToEdit = TrackedString() @@ -264,9 +272,23 @@ println("The number of edits is \(stringToEdit.numberOfEdits)") 虽然你可以在其他的源文件中实例化该结构体并且获取到`numberOfEdits`属性的值,但是你不能对其进行赋值。这样就能很好的告诉使用者,你只管使用,而不需要知道其实现细节。 +如果有必要你可以为`Getter`和`Setter`方法设定显式访问级别。下面的例子就是明确申明了`public`访问级别的`TrackedString`结构体。结构体的成员(包括`numberOfEdits`属性)拥有默认的访问级别`internal`。你可以结合`public`和`private(set)`修饰符把结构体中的`numberOfEdits`属性`Getter`方法的访问级别设置为`public`,而`Setter`方法的访问级别设置为`private`: + +```swift +public struct TrackedString { + public private(set) var numberOfEdits = 0 + public var value: String = "" { + didSet { + numberOfEdits++ + } + } + public init() {} +} +``` + ## 初始化 -我们可以给自定义的初始化方法指定访问级别,但是必须要低于或等于它所属类的访问级别。但如果该初始化方法是必须要使用的话,那它的访问级别就必须和所属类的访问级别相同。 +我们可以给自定义的初始化方法申明访问级别,但是要不高于它所属类的访问级别。但[必要构造器](TODO)例外,它的访问级别必须和所属类的访问级别相同。 如同函数或方法参数,初始化方法参数的访问级别也不能低于初始化方法的访问级别。 @@ -284,7 +306,7 @@ Swift为结构体、类都提供了一个默认的无参初始化方法,用于 ## 协议 -如果你想为一个协议明确的申明访问级别,那么有一点需要注意,就是你要确保该协议只在你申明的访问级别作用域中使用。 +如果想为一个协议明确的申明访问级别,那么需要注意一点,就是你要确保该协议只在你申明的访问级别作用域中使用。 协议中的每一个必须要实现的函数都具有和该协议相同的访问级别。这样才能确保该协议的使用者可以实现它所提供的函数。 @@ -298,17 +320,17 @@ Swift为结构体、类都提供了一个默认的无参初始化方法,用于 ### 协议一致性 类可以采用比自身访问级别低的协议。比如说,你可以定义一个`public`级别的类,可以让它在其他模块中使用,同时它也可以采用一个`internal`级别的协议,并且只能在定义了该协议的模块中使用。 -采用了协议的类的访问级别遵循它本身和采用协议中最低的访问级别。也就是说如果一个类是`public`级别,采用的协议是`internal`级别,那个采用了这个协议后,该类的访问级别也是`internal`。 +采用了协议的类的访问级别取它本身和所采用协议中最低的访问级别。也就是说如果一个类是`public`级别,采用的协议是`internal`级别,那么采用了这个协议后,该类的访问级别也是`internal`。 -如果你采用了协议,那么实现了协议必须的方法后,该方法的访问级别遵循协议的访问级别。比如说,一个`public`级别的类,采用了`internal`级别的协议,那么该类实现协议的方法至少也得是`internal`。 +如果你采用了协议,那么实现了协议所必须的方法后,该方法的访问级别遵循协议的访问级别。比如说,一个`public`级别的类,采用了`internal`级别的协议,那么该类实现协议的方法至少也得是`internal`。 -> 注意:在Swift中和Objective-C中一样,协议的一致性保证了一个类不可能在同一个程序中用不同的方法采用同一个协议。 +> 注意:Swift和Objective-C一样,协议的一致性保证了一个类不可能在同一个程序中用不同的方法采用同一个协议。 ## 扩展 你可以在条件允许的情况下对类、结构体、枚举进行扩展。扩展成员应该具有和原始类成员一致的访问级别。比如你扩展了一个公共类型,那么你新加的成员应该具有和原始成员一样的默认的`internal`访问级别。 -或者,你可以明确申明扩展的访问级别(比如使用`private extension`)给该扩展内所有成员指定一个新的默认访问级别。这个新的默认访问级别仍然可以被单独成员所指定的访问级别所覆盖。 +或者,你可以明确申明扩展的访问级别(比如使用`private extension`)给该扩展内所有成员申明一个新的默认访问级别。这个新的默认访问级别仍然可以被单独成员所申明的访问级别所覆盖。 ### 协议的扩展 @@ -316,12 +338,13 @@ Swift为结构体、类都提供了一个默认的无参初始化方法,用于 ## 泛型 -泛型类型或泛型函数的访问级别遵循泛型类型、函数本身、泛型类型参数三者中访问级别最低的级别。 +泛型类型或泛型函数的访问级别取泛型类型、函数本身、泛型类型参数三者中的最低访问级别。 ## 类型别名 -任何被你定义的类型别名都会被视作为不同的类型,这些类型用于访问控制。一个类型别名的访问级别可以低于或等于这个类型的访问级别。比如说,一个`private`级别的类型别名可以设定给一个`public`、`internal`、`private`的类型,但是一个`public`级别的类型别名只能设定给一个`public`级别的类型,不能设定给`internal`或`private`的类类型。 +任何你定义的类型别名都会被当作不同的类型,以便于进行访问控制。一个类型别名的访问级别不可高于原类型的访问级别。比如说,一个`private`级别的类型别名可以设定给一个`public`、`internal`、`private`的类型,但是一个`public`级别的类型别名只能设定给一个`public`级别的类型,不能设定给`internal`或`private` 级别的类型。 + +> 注意:这条规则也适用于为满足协议一致性而给相关类型命名别名的情况。 -> 注意:这条规则也适用于为满足协议一致性而给相关类型命名别名。 From 657e4589990b434b3f7b3121242547ba8683fc8f Mon Sep 17 00:00:00 2001 From: Siyu Yang Date: Tue, 30 Jun 2015 16:09:11 +0800 Subject: [PATCH 37/50] =?UTF-8?q?=E5=AE=8C=E6=88=90Chapter2=5FType=5FCasti?= =?UTF-8?q?ng=E9=83=A8=E5=88=86=E6=A0=A1=E5=AF=B9=E5=8F=8A=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/20_Type_Casting.md | 101 +++++++++++++++-------------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/source/chapter2/20_Type_Casting.md b/source/chapter2/20_Type_Casting.md index cea8fe3d..dc72a95f 100644 --- a/source/chapter2/20_Type_Casting.md +++ b/source/chapter2/20_Type_Casting.md @@ -1,5 +1,5 @@ > 翻译:[xiehurricane](https://github.com/xiehurricane) -> 校对:[happyming](https://github.com/happyming) +> 校对:[happyming](https://github.com/happyming) [yangsiy](https://github.com/yangsiy) # 类型转换(Type Casting) ----------------- @@ -14,16 +14,16 @@ _类型转换_可以判断实例的类型,也可以将实例看做是其父类或者子类的实例。 -类型转换在 Swift 中使用`is` 和 `as`操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。 +类型转换在 Swift 中使用 `is` 和 `as` 操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。 -你也可以用来检查一个类是否实现了某个协议,就像在 [Checking for Protocol Conformance](Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_363)部分讲述的一样。 +你也可以用它来检查一个类是否实现了某个协议,就像在 [Checking for Protocol Conformance](Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_363)部分讲述的一样。 ## 定义一个类层次作为例子 -你可以将它用在类和子类的层次结构上,检查特定类实例的类型并且转换这个类实例的类型成为这个层次结构中的其他类型。这下面的三个代码段定义了一个类层次和一个包含了几个这些类实例的数组,作为类型转换的例子。 +你可以将类型转换用在类和子类的层次结构上,检查特定类实例的类型并且转换这个类实例的类型成为这个层次结构中的其他类型。下面的三个代码段定义了一个类层次和一个包含了几个这些类实例的数组,作为类型转换的例子。 -第一个代码片段定义了一个新的基础类`MediaItem`。这个类为任何出现在数字媒体库的媒体项提供基础功能。特别的,它声明了一个 `String` 类型的 `name` 属性,和一个`init name`初始化器。(它假定所有的媒体项都有个名称。) +第一个代码片段定义了一个新的基础类 `MediaItem`。这个类为任何出现在数字媒体库的媒体项提供基础功能。特别的,它声明了一个 `String` 类型的 `name` 属性,和一个 `init name` 初始化器。(假定所有的媒体项都有个名称。) ```swift class MediaItem { @@ -34,7 +34,7 @@ class MediaItem { } ``` -下一个代码段定义了 `MediaItem` 的两个子类。第一个子类`Movie`,在父类(或者说基类)的基础上增加了一个 `director`(导演) 属性,和相应的初始化器。第二个类在父类的基础上增加了一个 `artist`(艺术家) 属性,和相应的初始化器: +下一个代码段定义了 `MediaItem` 的两个子类。第一个子类 `Movie` 封装了与电影相关的额外信息,在父类(或者说基类)的基础上增加了一个 `director`(导演)属性,和相应的初始化器。第二个子类 `Song`,在父类的基础上增加了一个 `artist`(艺术家)属性,和相应的初始化器: ```swift class Movie: MediaItem { @@ -54,7 +54,7 @@ class Song: MediaItem { } ``` -最后一个代码段创建了一个数组常量 `library`,包含两个`Movie`实例和三个`Song`实例。`library`的类型是在它被初始化时根据它数组中所包含的内容推断来的。Swift 的类型检测器能够演绎出`Movie` 和 `Song` 有共同的父类 `MediaItem` ,所以它推断出 `[MediaItem]` 类作为 `library` 的类型。 +最后一个代码段创建了一个数组常量 `library`,包含两个 `Movie` 实例和三个 `Song` 实例。`library` 的类型是在它被初始化时根据它数组中所包含的内容推断来的。Swift的类型检测器能够推理出 `Movie` 和 `Song` 有共同的父类 `MediaItem`,所以它推断出 `[MediaItem]` 类作为 `library` 的类型。 ```swift let library = [ @@ -67,14 +67,14 @@ let library = [ // the type of "library" is inferred to be [MediaItem] ``` -在幕后`library` 里存储的媒体项依然是 `Movie` 和 `Song` 类型的,但是,若你迭代它,取出的实例会是 `MediaItem` 类型的,而不是 `Movie` 和 `Song` 类型的。为了让它们作为它们本来的类型工作,你需要检查它们的类型或者向下转换它们的类型到其它类型,就像下面描述的一样。 +在幕后 `library` 里存储的媒体项依然是 `Movie` 和 `Song` 类型的。但是,若你迭代它,依次取出的实例会是 `MediaItem` 类型的,而不是 `Movie` 和 `Song` 类型。为了让它们作为原本的类型工作,你需要检查它们的类型或者向下转换它们到其它类型,就像下面描述的一样。 ## 检查类型(Checking Type) -用类型检查操作符(`is`)来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 `true` ,否则返回 `false` 。 +用类型检查操作符(`is`)来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 `true`,否则返回 `false`。 -下面的例子定义了两个变量,`movieCount` 和 `songCount`,用来计算数组`library` 中 `Movie` 和 `Song` 类型的实例数量。 +下面的例子定义了两个变量,`movieCount` 和 `songCount`,用来计算数组 `library` 中 `Movie` 和 `Song` 类型的实例数量。 ```swift var movieCount = 0 @@ -88,38 +88,38 @@ for item in library { } } -println("Media library contains \(movieCount) movies and \(songCount) songs") +print("Media library contains \(movieCount) movies and \(songCount) songs") // prints "Media library contains 2 movies and 3 songs" ``` -示例迭代了数组 `library` 中的所有项。每一次, `for`-`in` 循环设置 +示例迭代了数组 `library` 中的所有项。每一次,`for`-`in` 循环设置 `item` 为数组中的下一个 `MediaItem`。 -若当前 `MediaItem` 是一个 `Movie` 类型的实例, `item is Movie` 返回 +若当前 `MediaItem` 是一个 `Movie` 类型的实例,`item is Movie` 返回 `true`,相反返回 `false`。同样的,`item is -Song`检查item是否为`Song`类型的实例。在循环结束后,`movieCount` 和 `songCount`的值就是被找到属于各自的类型的实例数量。 +Song` 检查item是否为 `Song` 类型的实例。在循环结束后,`movieCount` 和 `songCount` 的值就是被找到属于各自的类型的实例数量。 ## 向下转型(Downcasting) -某类型的一个常量或变量可能在幕后实际上属于一个子类。你可以相信,上面就是这种情况。你可以尝试向下转到它的子类型,用类型转换操作符(`as`) +某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用类型转换操作符(`as?` 或 `as!`) -因为向下转型可能会失败,类型转型操作符带有两种不同形式。可选形式( optional form) `as?` 返回一个你试图下转成的类型的可选值(optional value)。强制形式 `as` 把试图向下转型和强制解包(force-unwraps)结果作为一个混合动作。 +因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式(conditional form) `as?` 返回一个你试图向下转成的类型的可选值(optional value)。强制形式 `as!` 把试图向下转型和强制解包(force-unwraps)结果作为一个混合动作。 -当你不确定向下转型可以成功时,用类型转换的可选形式(`as?`)。可选形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 `nil` 。这使你能够检查向下转型是否成功。 +当你不确定向下转型可以成功时,用类型转换的条件形式(`as?`)。条件形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 `nil`。这使你能够检查向下转型是否成功。 -只有你可以确定向下转型一定会成功时,才使用强制形式。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。 +只有你可以确定向下转型一定会成功时,才使用强制形式(`as!`)。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。 -下面的例子,迭代了`library`里的每一个 `MediaItem` ,并打印出适当的描述。要这样做,`item`需要真正作为`Movie` 或 `Song`的类型来使用。不仅仅是作为 `MediaItem`。为了能够使用`Movie` 或 `Song`的 `director` 或 `artist`属性,这是必要的。 +下面的例子,迭代了 `library` 里的每一个 `MediaItem`,并打印出适当的描述。要这样做,`item` 需要真正作为 `Movie` 或 `Song` 的类型来使用,不仅仅是作为 `MediaItem`。为了能够在描述中使用 `Movie` 或 `Song` 的 `director` 或 `artist` 属性,这是必要的。 -在这个示例中,数组中的每一个`item`可能是 `Movie` 或 `Song`。 事前你不知道每个`item`的真实类型,所以这里使用可选形式的类型转换 (`as?`)去检查循环里的每次下转。 +在这个示例中,数组中的每一个 `item` 可能是 `Movie` 或 `Song`。事前你不知道每个 `item` 的真实类型,所以这里使用条件形式的类型转换(`as?`)去检查循环里的每次下转。 ```swift for item in library { if let movie = item as? Movie { - println("Movie: '\(movie.name)', dir. \(movie.director)") + print("Movie: '\(movie.name)', dir. \(movie.director)") } else if let song = item as? Song { - println("Song: '\(song.name)', by \(song.artist)") + print("Song: '\(song.name)', by \(song.artist)") } } @@ -131,18 +131,19 @@ for item in library { ``` 示例首先试图将 `item` 下转为 `Movie`。因为 `item` 是一个 `MediaItem` -类型的实例,它可能是一个`Movie`;同样,它可能是一个 `Song`,或者仅仅是基类 -`MediaItem`。因为不确定,`as?`形式在试图下转时将返还一个可选值。 `item as Movie` 的返回值是`Movie?`类型或 “optional `Movie`”。 +类型的实例,它可能是一个 `Movie`;同样,它也可能是一个 `Song`,或者仅仅是基类 +`MediaItem`。因为不确定,`as?`形式在试图下转时将返回一个可选值。`item as? Movie` 的返回值是 `Movie?` 或 “可选 `Movie`”类型。 当向下转型为 `Movie` 应用在两个 `Song` -实例时将会失败。为了处理这种情况,上面的例子使用了可选绑定(optional binding)来检查可选 `Movie`真的包含一个值(这个是为了判断下转是否成功。)可选绑定是这样写的“`if let movie = item as? Movie`”,可以这样解读: +实例时将会失败。为了处理这种情况,上面的例子使用了可选绑定(optional binding)来检查可选 `Movie` 真的包含一个值(这个是为了判断下转是否成功。)可选绑定是这样写的“`if let movie = item as? Movie`”,可以这样解读: -“尝试将 `item` 转为 `Movie`类型。若成功,设置一个新的临时常量 `movie` 来存储返回的可选`Movie`” +“尝试将 `item` 转为 `Movie` 类型。若成功,设置一个新的临时常量 `movie` 来存储返回的可选 `Movie`” -若向下转型成功,然后`movie`的属性将用于打印一个`Movie`实例的描述,包括它的导演的名字`director`。当`Song`被找到时,一个相近的原理被用来检测 `Song` 实例和打印它的描述。 +若向下转型成功,然后 `movie` 的属性将用于打印一个 `Movie` 实例的描述,包括它的导演的名字 `director` 。相近的原理被用来检测 `Song` 实例,当 `Song` 被找到时则打印它的描述(包含 `artist` 的名字)。 > 注意: -转换没有真的改变实例或它的值。潜在的根本的实例保持不变;只是简单地把它作为它被转换成的类来使用。 + +>转换没有真的改变实例或它的值。潜在的根本的实例保持不变;只是简单地把它作为它被转换成的类来使用。 ## `Any`和`AnyObject`的类型转换 @@ -153,11 +154,12 @@ Swift为不确定类型提供了两种特殊类型别名: * `Any`可以表示任何类型,包括方法类型(function types)。 > 注意: -只有当你明确的需要它的行为和功能时才使用`Any`和`AnyObject`。在你的代码里使用你期望的明确的类型总是更好的。 + +>只有当你明确的需要它的行为和功能时才使用`Any`和`AnyObject`。在你的代码里使用你期望的明确的类型总是更好的。 ### `AnyObject`类型 -当需要在工作中使用 Cocoa APIs,它一般接收一个`[AnyObject]`类型的数组,或者说“一个任何对象类型的数组”。这是因为 Objective-C 没有明确的类型化数组。但是,你常常可以确定包含在仅从你知道的 API 信息提供的这样一个数组中的对象的类型。 +当在工作中使用 Cocoa APIs,我们一般会接收一个`[AnyObject]`类型的数组,或者说“一个任何对象类型的数组”。这是因为 Objective-C 没有明确的类型化数组。但是,你常常可以从 API 提供的信息中清晰地确定数组中对象的类型。 在这些情况下,你可以使用强制形式的类型转换(`as`)来下转在数组中的每一项到比 `AnyObject` 更明确的类型,不需要可选解析(optional unwrapping)。 @@ -171,23 +173,23 @@ let someObjects: [AnyObject] = [ ] ``` -因为知道这个数组只包含 `Movie` 实例,你可以直接用(`as`)下转并解包到不可选的`Movie`类型(ps:其实就是我们常用的正常类型,这里是为了和可选类型相对比)。 +因为知道这个数组只包含 `Movie` 实例,你可以直接用(`as!`)下转并解包到不可选的`Movie`类型: ```swift for object in someObjects { - let movie = object as Movie - println("Movie: '\(movie.name)', dir. \(movie.director)") + let movie = object as! Movie + print("Movie: '\(movie.name)', dir. \(movie.director)") } // Movie: '2001: A Space Odyssey', dir. Stanley Kubrick // Movie: 'Moon', dir. Duncan Jones // Movie: 'Alien', dir. Ridley Scott ``` -为了变为一个更短的形式,下转`someObjects`数组为`[Movie]`类型来代替下转每一项方式。 +为了变为一个更短的形式,下转`someObjects`数组为`[Movie]`类型来代替下转数组中每一项的方式。 ```swift for movie in someObjects as! [Movie] { - println("Movie: '\(movie.name)', dir. \(movie.director)") + print("Movie: '\(movie.name)', dir. \(movie.director)") } // Movie: '2001: A Space Odyssey', dir. Stanley Kubrick // Movie: 'Moon', dir. Duncan Jones @@ -196,7 +198,7 @@ for movie in someObjects as! [Movie] { ### `Any`类型 -这里有个示例,使用 `Any` 类型来和混合的不同类型一起工作,包括非`class`类型。它创建了一个可以存储`Any`类型的数组 `things`。 +这里有个示例,使用 `Any` 类型来和混合的不同类型一起工作,包括方法类型和非 `class` 类型。它创建了一个可以存储`Any`类型的数组 `things`。 ```swift var things = [Any]() @@ -211,33 +213,33 @@ things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman")) things.append({ (name: String) -> String in "Hello, \(name)" }) ``` -`things` 数组包含两个 `Int` 值,2个 `Double` 值,1个 `String` 值,一个元组 `(Double, Double)` ,Ivan Reitman 导演的电影“Ghostbusters”。 +`things` 数组包含两个 `Int` 值,2个 `Double` 值,1个 `String` 值,一个元组 `(Double, Double)` ,电影“Ghostbusters”,和一个获取 `String` 值并返回另一个 `String` 值的闭包表达式。 -你可以在 `switch` `cases`里用`is` 和 `as` 操作符来发觉只知道是 `Any` 或 `AnyObject`的常量或变量的类型。 下面的示例迭代 `things`数组中的每一项的并用`switch`语句查找每一项的类型。这几种`switch`语句的情形绑定它们匹配的值到一个规定类型的常量,让它们可以打印它们的值: +你可以在 `switch` 表达式的cases中使用 `is` 和 `as` 操作符来发觉只知道是 `Any` 或 `AnyObject` 的常量或变量的类型。下面的示例迭代 `things` 数组中的每一项的并用`switch`语句查找每一项的类型。这几种 `switch` 语句的情形绑定它们匹配的值到一个规定类型的常量,让它们的值可以被打印: ```swift for thing in things { switch thing { case 0 as Int: - println("zero as an Int") + print("zero as an Int") case 0 as Double: - println("zero as a Double") + print("zero as a Double") case let someInt as Int: - println("an integer value of \(someInt)") + print("an integer value of \(someInt)") case let someDouble as Double where someDouble > 0: - println("a positive double value of \(someDouble)") + print("a positive double value of \(someDouble)") case is Double: - println("some other double value that I don't want to print") + print("some other double value that I don't want to print") case let someString as String: - println("a string value of \"\(someString)\"") + print("a string value of \"\(someString)\"") case let (x, y) as (Double, Double): - println("an (x, y) point at \(x), \(y)") + print("an (x, y) point at \(x), \(y)") case let movie as Movie: - println("a movie called '\(movie.name)', dir. \(movie.director)") + print("a movie called '\(movie.name)', dir. \(movie.director)") case let stringConverter as String -> String: - println(stringConverter("Michael")) + print(stringConverter("Michael")) default: - println("something else") + print("something else") } } @@ -253,4 +255,5 @@ for thing in things { > 注意: -在一个switch语句的case中使用强制形式的类型转换操作符(as, 而不是 as?)来检查和转换到一个明确的类型。在 switch case 语句的内容中这种检查总是安全的。 + +>在一个switch语句的case中使用强制形式的类型转换操作符(as, 而不是 as?)来检查和转换到一个明确的类型。在 `switch` case 语句的内容中这种检查总是安全的。 From 19f3bd8ca1d42e302044e3af17ea7d677100af85 Mon Sep 17 00:00:00 2001 From: KYawn Date: Tue, 30 Jun 2015 18:12:21 +0800 Subject: [PATCH 38/50] swift 2.0 chapter3 01 and 06 --- .../01_About_the_Language_Reference.md | 24 ++- source/chapter3/06_Attributes.md | 183 ++++++++++++------ 2 files changed, 135 insertions(+), 72 deletions(-) diff --git a/source/chapter3/01_About_the_Language_Reference.md b/source/chapter3/01_About_the_Language_Reference.md index aafce2d3..f2f2ef11 100755 --- a/source/chapter3/01_About_the_Language_Reference.md +++ b/source/chapter3/01_About_the_Language_Reference.md @@ -1,5 +1,5 @@ > 翻译:[dabing1022](https://github.com/dabing1022) -> 校对:[numbbbbb](https://github.com/numbbbbb) +> 校对:[numbbbbb](https://github.com/numbbbbb), [KYawn](https://github.com/KYawn) # 关于语言附注 @@ -11,28 +11,32 @@ 本书的这一节描述了Swift编程语言的形式语法。这里描述的语法是为了帮助您更详细的了解该语言,而不是让您直接实现一个解析器或编译器。 - -Swift语言相对小点,这是由于在Swift代码中几乎无处不在的许多常见的的类型,函数以及运算符都由Swift标准库来定义。虽然这些类型,函数和运算符不是Swift语言本身的一部分,但是它们被广泛用于这本书的讨论和代码范例。 +Swift语言相对小一点,这是由于在Swift代码中几乎所有常见的类型、函数以及运算符都已经在Swift标准库中定义了。虽然这些类型、函数和运算符并不是Swift语言自身的一部分,但是它们被广泛应用于本书的讨论和代码范例中。 ## 如何阅读语法 -用来描述Swift编程语言形式语法的记法遵循下面几个约定: +用来描述Swift编程语言形式语法的标记遵循下面几个约定: -- 箭头(→)用来标记语法产式,可以被理解为“可以包含”。 -- 句法范畴由*斜体*文字表示,并出现在一个语法产式规则两侧。 -- 义词和标点符号由粗体固定宽度的文本显示和只出现在一个语法产式规则的右边。 +- 箭头(→)用来标记语法产式,可以理解为“可以包含”。 +- *斜体*文字用来表示句法分类,并出现在一个语法产式规则两侧。 +- 义词和标点符号由粗体固定宽度的文本标记,而且只出现在一个语法产式规则的右侧。 - 选择性的语法产式由竖线(|)分隔。当可选用的语法产式太多时,为了阅读方便,它们将被拆分为多行语法产式规则。 -- 在少数情况下,常规字体文字用来描述语法产式规则的右边。 -- 可选的句法范畴和文字用尾标`opt`来标记。 +- 少数情况下,常规字体文字用来描述语法产式规则的右边。 +- 可选的句法分类和文字用尾标`opt`来标记。 举个例子,getter-setter的语法块的定义如下: > GRAMMAR OF A GETTER-SETTER BLOCK > *getter-setter-block* → {­ [*getter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/getter-clause) [­*setter-clause*­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/setter-clause)*opt* ­}­ | {­ [*setter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/setter-clause) [­*getter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/getter-clause)­}­ -这个定义表明,一个getter-setter方法​​块可以由一个getter子句后跟一个可选的setter子句构成,用大括号括起来,或者由一个setter子句后跟一个getter子句构成,用大括号括起来。上述的文法产生等价于下面的两个产生,明确阐明如何二中择一: +这个定义表明,一个getter-setter方法​​块可以由一个getter子句后跟一个可选的setter子句构成,然后用大括号括起来,或者由一个setter子句后跟一个getter子句构成,然后用大括号括起来。下面的两个语法产式等价于上述的语法产式,并明确指出了如何取舍: > GRAMMAR OF A GETTER-SETTER BLOCK > getter-setter-block → {­ [*getter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/getter-clause) [*­setter-clause*­](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/setter-clause)*opt* ­}­­ > getter-setter-block → {­ [*setter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/setter-clause) [*­getter-clause*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/swift/grammar/getter-clause)­}­ + + + + + diff --git a/source/chapter3/06_Attributes.md b/source/chapter3/06_Attributes.md index 2ffa3872..e6063258 100755 --- a/source/chapter3/06_Attributes.md +++ b/source/chapter3/06_Attributes.md @@ -1,5 +1,5 @@ > 翻译:[Hawstein](https://github.com/Hawstein) -> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai) +> 校对:[numbbbbb](https://github.com/numbbbbb), [stanzhai](https://github.com/stanzhai), [KYawn](https://github.com/KYawn) # 特性 ----------------- @@ -9,7 +9,7 @@ - [声明特性](#declaration_attributes) - [类型特性](#type_attributes) -特性提供了关于声明和类型的更多信息。在Swift中有两类特性,用于修饰声明的以及用于修饰类型的。例如,`required`特性,当应用于一个类的指定或便利初始化器声明时,表明它的每个子类都必须实现那个初始化器。再比如`noreturn`特性,当应用于函数或方法类型时,表明该函数或方法不会返回到它的调用者。 +特性提供了关于声明和类型的更多信息。在Swift中有两类特性,用于修饰声明的以及用于修饰类型的。 通过以下方式指定一个特性:符号`@`后面跟特性名,如果包含参数,则把参数带上: @@ -23,30 +23,44 @@ 声明特性只能应用于声明。然而,你也可以将`noreturn`特性应用于函数或方法类型。 -`availability` +`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). -将`availability`特性用于声明时,将表示该声明的生命周期会依赖于特定的平台和操作系统版本。 -`availability`特性总会与参数列表一同出现,该参数列表至少有两个参数,参数之间由逗号分隔。第一个参数由以下这些平台名字中的一个起头:iOS, iOSApplicationExtension, OSX, or OSXApplicationExtension。当然,你也可以用一个星号(*)来表示,该声明在上面提到的所有平台上都是有效的。剩下的参数,可以以任何顺序出现,并且可以附加关于声明生命周期的附加信息,包括重要的里程碑。 +`available` -- `unavailable`参数表示该声明在特定的平台上是无效的 +将`available`特性用于声明时,意味着该声明的生命周期会依赖于特定的平台和操作系统版本。 +`available`特性经常与参数列表一同出现,该参数列表至少有两个参数,参数之间由逗号分隔。这些参数由以下这些平台名字中的一个起头: -- `introduced`参数表示:特定的平台上,该声明被使用的第一个版本。格式如下:

`introduced=version number`

这里的`version number`由一个正的十进制整数或浮点数构成。 +- `iOS` +- `iOSApplicationExtension` +- `OSX` +- `OSXApplicationExtension` +- `watchOS` -- `deprecated`参数表示:特定的平台上,该声明被建议弃用的第一个版本。格式如下: +当然,你也可以用一个星号(*)来表示,该声明在上面提到的所有平台上都是有效的。 + +剩下的参数,可以以任何顺序出现,并且可以添加关于声明生命周期的附加信息,包括重要的里程碑。 + +- `unavailable`参数表示:该声明在特定的平台上是无效的 + +- `introduced`参数表示:该声明第一次被引入时所在平台的版本。格式如下: +

`introduced=version number`

这里的`version number`由一个正的十进制整数或浮点数构成。 + +- `deprecated`参数表示:该声明第一次被建议弃用时所在平台的版本。格式如下:

`deprecated=version number`

这里的`version number`由一个正的十进制整数或浮点数构成。 -- `obsoleted`参数表示:特定的平台上,该声明被弃用的第一个版本。格式如下: -

`deprecated=version number`

这里的`version number`由一个正的十进制整数或浮点数构成。 +- `obsoleted`参数表示:该声明第一次被弃用时所在平台的版本。当一个声明被弃用时,它就从此平台中被移除,不能再被使用。格式如下: +

`obsoleted=version number`

这里的`version number`由一个正的十进制整数或浮点数构成。 -- `message`参数用来提供文本信息,并在因使用建议弃用或者被弃用的声明而遇到警告或错误时,由编译器抛出。格式如下: +- `message`参数用来提供文本信息。当使用建议弃用或者被弃用的声明时,编译器会抛出错误或警告信息。格式如下:

`message=message`

这里的`message`由一个字符串文字构成。 -- `renamed`参数用来提供文本信息,用以表示被重命名的声明的新名字。当使用这个重命名的声明遇到错误时,该新名字会被编译器显示出来。格式如下: +- `renamed`参数用来提供文本信息,用以表示被重命名的声明的新名字。当使用这个重命名的声明遇到错误时,编译器会显示出该新名字。格式如下:

`renamed=new name`

这里的`new name`由一个字符串文字构成。 -你可以将`renamed`参数和`unavailable`参数以及类型别名声明组合使用,以向用户表示:在你的代码中,一个声明已经被重命名。当一个声明的名字在一个框架或者库的不同发布版本间发生变化时,这会相当管用。 +你可以将`renamed`参数和`unavailable`参数以及类型别名声明组合使用,以向用户表示:在你的代码中,一个声明已经被重命名。当一个声明的名字在一个框架或者库的不同发布版本间发生变化时,这会相当有用。 ```swift // First release @@ -58,50 +72,34 @@ protocol MyRenamedProtocol { // protocol definition } -@availability(*, unavailable, renamed="MyRenamedProtocol") +@available(*, unavailable, renamed="MyRenamedProtocol") typealias MyProtocol = MyRenamedProtocol ``` -你可以在一个单独的声明上使用多个`availability`特性,以详细说明该声明在不同平台上的有效性。编译器只有在当前的目标平台和`availability`特性中指定的平台匹配时,才会使用`availability`特性 +你可以在一个单独的声明上使用多个`available`特性,以详细说明该声明在不同平台上的有效性。编译器只有在当前的目标平台和`available`特性中指定的平台匹配时,才会使用`available`特性 -`autoclosure` +如果`available`特性除了平台名称参数外,只指定了一个`introduced `参数,那么可以使用以下简写语法代替: -这个属性通过把表达式自动封装成不带参数的闭包来延迟表达式的计算。这个属性使用在函数参数声明或者不带参数但是返回表达式类型的方法类型上。含有```autoclosure```属性的声明同时也具有```noescape```的特性,除非传递一个可选的参数属性```escaping```,请看[函数类型](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html#//apple_ref/doc/uid/TP40014097-CH31-ID449)。 +@available(`platform name` `version number`, *) -`noescape` - -在函数或者方法声明上使用该属性表示参数将不会被存储用作后续的计算,其用来确保不会超出函数调用的声明周期。使用```noescape```声明属性的函数类型不需要显式的使用```self```,对于其属性或者方法来说。 - -`noreturn` - -该特性用于修饰函数或方法声明,表明该函数或方法的对应类型,`T`,是`@noreturn T`。你可以用这个特性修饰函数或方法的类型,这样一来,函数或方法就不会返回到它的调用者中去。 - -对于一个没有用`noreturn`特性标记的函数或方法,你可以将它重写(override)为用该特性标记的。相反,对于一个已经用`noreturn`特性标记的函数或方法,你则不可以将它重写为没使用该特性标记的。相同的规则试用于当你在一个comforming类型中实现一个协议方法时。 - -`NSApplicationMain` -在类上使用该属性表示该类是应用程序委托类,使用该属性与调用```NSApplicationMain```函数并且把该类的名字作为委托类的名字传递给函数的效果相同。 - -如果你不想使用这个属性,可以提供一个```main.swift```文件,并且提供一个```main```函数去调用```NSApplicationMain```函数。比如,如果你的应用程序使用一个派生于```NSApplication```的自定义子类作为主要类,你可以调用```NSApplicationMain```函数而不是使用该属性。 - - -`NSCopying` - -该特性用于修饰一个类的存储型变量属性。该特性将使属性的setter与属性值的一个副本合成,由`copyWithZone`方法返回,而不是属性本身的值。该属性的类型必需遵循`NSCopying`协议。 - -`NSCopying`特性的行为与Objective-C中的`copy`特性相似。 - -`NSManaged` - -该特性用于修饰`NSManagedObject`子类中的存储型变量属性,表明属性的存储和实现由Core Data在运行时基于相关实体描述动态提供。 +`available`特性的简写语法可以简明地表达出多个平台的可用性。尽管这两种形式在功能上是相同的,但请尽可能地使用简明语法形式。 +```swift +@available(iOS 8.0, OSX 10.10, *) +class MyClass { + // class definition +} +``` `objc` -该特性用于修饰任意可以在Objective-C中表示的声明,比如,非嵌套类,协议,类和协议中的属性和方法(包含getter和setter),初始化器,析构器,以及下标。`objc`特性告诉编译器该声明可以在Objective-C代码中使用。 +该特性用于修饰任何可以在Objective-C中表示的声明。比如,非嵌套类、协议、非泛型枚举(仅限整型值类型)、类和协议的属性和方法(包括`getter`和`setter`)、构造器、析构器以及下标。`objc`特性告诉编译器这个声明可以在Objective-C代码中使用。 -如果你将`objc`特性应用于一个类或协议,它也会隐式地应用于那个类或协议的成员。对于标记了`objc`特性的类,编译器会隐式地为它的子类添加`objc`特性。标记了`objc`特性的协议不能继承自没有标记`objc`的协议。 +如果你将`objc`特性应用于一个类或协议,它也会隐式地应用于那个类的成员或协议。对于标记了`objc`特性的类,编译器会隐式地为它的子类添加`objc`特性。标记了`objc`特性的协议不能继承没有标记`objc`的协议。 -`objc`特性有一个可选的参数,由标记符组成。当你想把`objc`所修饰的实体以一个不同的名字暴露给Objective-C,你就可以使用这个特性参数。你可以使用这个参数来命名类,协议,方法,getters,setters,以及初始化器。下面的例子把`ExampleClass`中`enabled`属性的getter暴露给Objective-C,名字是`isEnabled`,而不是它原来的属性名。 +如果你将`objc`特性应用于枚举,每一个枚举的`case`都会以枚举名称和`case`名称组合的方式暴露在Objective-C代码中。例如:一个名为`Venus`的`case`在`Planet`枚举中,这个`case`暴露在Objective-C代码中时叫做`PlanetVenus`。 + +`objc`特性有一个可选的参数,由标记符组成。当你想把`objc`所修饰的实体以一个不同的名字暴露给Objective-C时,你就可以使用这个特性参数。你可以使用这个参数来命名类,协议,方法,getters,setters,以及构造器。下面的例子把`ExampleClass`中`enabled`属性的getter暴露给Objective-C,名字是`isEnabled`,而不是它原来的属性名。 ```swift @objc @@ -114,17 +112,64 @@ class ExampleClass { } ``` -`optional` +`noescape` -用该特性修饰协议的属性,方法或下标成员,表示实现这些成员并不需要一致性类型(conforming type)。 +在函数或者方法声明上使用该特性,它表示参数将不会被存储用作后续的计算,其用来确保不会超出函数调用的生命周期。对于其属性或方法来说,使用`noescape`声明属性的函数类型不需要显式的使用`self.`。 -你只能用`optional`特性修饰那些标记了`objc`特性的协议。因此,只有类类型可以adopt和comform to那些包含可选成员需求的协议。更多关于如何使用`optional`特性以及如何访问可选协议成员的指导,例如,当你不确定一个conforming类型是否实现了它们,请见:[可选协议需求]()。 +`nonobjc` -`required` +该特性用于方法、属性、下标、或构造器的声明,这些声明本是可以在Objective-C代码中表示的。使用`nonobjc`特性告诉编译器这个声明不能在Objective-C代码中使用。 -用该特性修饰一个类的指定或便利初始化器,表示该类的所有子类都必需实现该初始化器。 +可以使用`nonobjc`特性解决标有`objc`的类中桥接方法的循环问题,该特性还允许标有`objc`的类的构造器和方法进行重载(overload)。 -加了该特性的指定初始化器必需显式地实现,而便利初始化器既可显式地实现,也可以在子类实现了超类所有指定初始化器后继承而来(或者当子类使用便利初始化器重写了指定初始化器)。 +标有`nonobjc`特性的方法不能重写(override)一个标有`objc`特性的方法。然而,标有`objc`特性的方法可以重写标有`nonobjc`特性的方法。同样,标有`nonobjc`特性的方法不能满足一个需要标有`@objc`特性的方法的协议。 + +`noreturn` + +该特性用于修饰函数或方法声明,表明该函数或方法的对应类型,`T`,是`@noreturn T`。你可以用这个特性修饰函数或方法的类型,这样一来,函数或方法就不会返回到它的调用者中去。 + +对于一个没有用`noreturn`特性标记的函数或方法,你可以将它重写为用该特性标记的。相反,对于一个已经用`noreturn`特性标记的函数或方法,你则不可以将它重写为没使用该特性标记的。当你在一个comforming类型中实现一个协议方法时,该规则同样适用。 + +`NSApplicationMain` + +在类上使用该特性表示该类是应用程序委托类,使用该特性与调用`NSApplicationMain(_:_:)`函数并且把该类的名字作为委托类的名字传递给函数的效果相同。 + +如果你不想使用这个特性,可以提供一个`main.swift`文件,并且提供一个`main`函数去调用`NSApplicationMain(_:_:)`函数。比如,如果你的应用程序使用一个派生于`NSApplication`的自定义子类作为主要类,你可以调用`NSApplicationMain`函数而不是使用该特性。 + +`NSCopying` + +该特性用于修饰一个类的存储型变量属性。该特性将使属性的setter与属性值的一个副本合成,这个值由`copyWithZone(_:)`方法返回,而不是属性本身的值。该属性的类型必需遵循`NSCopying`协议。 + +`NSCopying`特性的原理与Objective-C中的`copy`特性相似。 + +`NSManaged` + +该特性用于修饰`NSManagedObject`子类中的存储型变量属性,表明属性的存储和实现由Core Data在运行时基于相关实体描述动态提供。 + +`testable` + +该特性用于`import`声明可以测试的编译模块,它能访问任何标有`internal`权限标识符的实体,这和将它声明为`public`权限标识符有同样的效果。 + +`UIApplicationMain` + +在类上使用该特性表示该类是应用程序委托类,使用该特性与调用`UIApplicationMain(_:_:)`函数并且把该类的名字作为委托类的名字传递给函数的效果相同。 + +如果你不想使用这个特性,可以提供一个`main.swift`文件,并且提供一个`main`函数去调用`UIApplicationMain(_:_:)`函数。比如,如果你的应用程序使用一个派生于`UIApplication`的自定义子类作为主要类,你可以调用`UIApplicationMain`函数而不是使用该特性。 + +`warn_unused_result` + +该特性应用于方法或函数声明,当方法或函数被调用,但其结果未被使用时,该特性会让编译器会产生警告。 + +你可以使用这个特性提供一个警告信息,这个警告信息是关于不正确地使用未变异的方法的,这个方法也有一个对应的变异方法。 + +`warn_unused_result`有下面两个可选的参数。 + +- `message`参数用来提供警告信息,并在因当方法或函数被调用,但其结果未被使用时,显示警告信息。格式如下: +

`message=message`

这里的`message`由一个字符串文字构成。 + +- `mutable_variant`参数用于提供变异方法的名称,如果未变异方法以一个可变的值被调用而且其结果并未被使用时,应该使用此变异方法。格式如下(方法名有字符串构成):

`mutable_variant=method name`

+ +比如,Swift标准库提供了变异方法`sortInPlace()`和未变异方法`sort()`集合,它们的元素生成器符合`Comparable`协议。如果你调用了`sort()`方法,而没有使用它的结果,很有可能,你打算使用变异方法`sortInPlace()`替代。 ### Interface Builder使用的声明特性 @@ -137,22 +182,36 @@ Interface Builder特性是Interface Builder用来与Xcode同步的声明特性 类型特性只能用于修饰类型。然而,你也可以用`noreturn`特性去修饰函数或方法声明。 -`auto_closure` +`convention` -这个特性通过自动地将表达式封闭到一个无参数闭包中来延迟表达式的求值。使用该特性修饰无参的函数或方法类型,返回表达式的类型。一个如何使用`auto_closure`特性的例子,见[函数类型]() +该特性用于函数的类型,它指出函数调用的约定。 + +`convention`特性有下面几个可选的参数。 + +- `swift`参数用于表明一个Swift函数引用。这是Swift中标准的函数值调用约定。 + +- `block`参数用于表明一个Objective-C兼容的块引用。函数值表示为一个块对象的引用,这是一个`id-`兼容的Objective-C对象,对象中嵌入了调用函数。调用函数使用C的调用约定。 + +- `c`参数用于表明一个C函数引用。函数值没有上下文,这个函数也使用C的调用约定。 + +使用C函数调用约定的函数也可用作使用Objective-C块调用约定的函数,同时使用Objective-C块调用约定的函数也可用作使用Swift函数调用约定的函数。然而,只有非泛型的全局函数和本地函数或者不使用任何本地变量的闭包可以被用作使用C函数调用约定的函数。 `noreturn` 该特性用于修饰函数或方法的类型,表明该函数或方法不会返回到它的调用者中去。你也可以用它标记函数或方法的声明,表示函数或方法的相应类型,`T`,是`@noreturn T`。 -> 特性语法 -> *特性* → **@** [*特性名*](..\chapter3\06_Attributes.html#attribute_name) [*特性参数子句*](..\chapter3\06_Attributes.html#attribute_argument_clause) _可选_ -> *特性名* → [*标识符*](LexicalStructure.html#identifier) -> *特性参数子句* → **(** [*平衡令牌列表*](..\chapter3\06_Attributes.html#balanced_tokens) _可选_ **)** -> *特性(Attributes)列表* → [*特色*](..\chapter3\06_Attributes.html#attribute) [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ -> *平衡令牌列表* → [*平衡令牌*](..\chapter3\06_Attributes.html#balanced_token) [*平衡令牌列表*](..\chapter3\06_Attributes.html#balanced_tokens) _可选_ -> *平衡令牌* → **(** [*平衡令牌列表*](..\chapter3\06_Attributes.html#balanced_tokens) _可选_ **)** -> *平衡令牌* → **[** [*平衡令牌列表*](..\chapter3\06_Attributes.html#balanced_tokens) _可选_ **]** -> *平衡令牌* → **{** [*平衡令牌列表*](..\chapter3\06_Attributes.html#balanced_tokens) _可选_ **}** +> 特性语法 +> *特性* → **@** [*特性名*](#attribute_name) [*特性参数子句*](#attribute_argument_clause) _可选_ +> *特性名* → [*标识符*](02_Lexical_Structure.html#identifiers) +> *特性参数子句* → **(** [*平衡令牌列表*](#balanced_tokens) _可选_ **)** +> *特性(Attributes)列表* → [*特色*](#attribute) [*特性(Attributes)列表*](#attributes) _可选_ +> *平衡令牌列表* → [*平衡令牌*](#balanced_token) [*平衡令牌列表*](#balanced_tokens) _可选_ +> *平衡令牌* → **(** [*平衡令牌列表*](#balanced_tokens) _可选_ **)** +> *平衡令牌* → **[** [*平衡令牌列表*](#balanced_tokens) _可选_ **]** +> *平衡令牌* → **{** [*平衡令牌列表*](#balanced_tokens) _可选_ **}** > *平衡令牌* → **任意标识符, 关键字, 字面量或运算符** > *平衡令牌* → **任意标点除了(, ), [, ], {, 或 }** + + + + From 134c3898ee2a331fe3b156f34c6ac1a62a8c0006 Mon Sep 17 00:00:00 2001 From: shanksyang Date: Tue, 30 Jun 2015 19:24:53 +0800 Subject: [PATCH 39/50] Swift2.0 pre-release,12_subscript --- source/chapter2/12_Subscripts.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/chapter2/12_Subscripts.md b/source/chapter2/12_Subscripts.md index 7bef609e..d9e4db4e 100755 --- a/source/chapter2/12_Subscripts.md +++ b/source/chapter2/12_Subscripts.md @@ -11,9 +11,9 @@ - [下标脚本用法](#subscript_usage) - [下标脚本选项](#subscript_options) -*下标脚本* 可以定义在类(Class)、结构体(structure)和枚举(enumeration)这些目标中,可以认为是访问对象、集合或序列的快捷方式,不需要再调用实例的特定的赋值和访问方法。举例来说,用下标脚本访问一个数组(Array)实例中的元素可以这样写 `someArray[index]` ,访问字典(Dictionary)实例中的元素可以这样写 `someDictionary[key]`。 +*下标脚本* 可以定义在类(Class)、结构体(structure)和枚举(enumeration)这些目标中,可以认为是访问集合(collection),列表(list)或序列(sequence的快捷方式,使用下标脚本的索引设置和获取值,不需要再调用实例的特定的赋值和访问方法。举例来说,用下标脚本访问一个数组(Array)实例中的元素可以这样写 `someArray[index]` ,访问字典(Dictionary)实例中的元素可以这样写 `someDictionary[key]`。 -对于同一个目标可以定义多个下标脚本,通过索引值类型的不同来进行重载,而且索引值的个数可以是多个。 +对于同一个目标可以定义多个下标脚本,通过索引值类型的不同来进行重载,下标脚本不限于单个纬度,你可以定义多个入参的下标脚本满足自定义类型的需求。 > 译者:这里附属脚本重载在本小节中原文并没有任何演示 @@ -63,7 +63,7 @@ println("3的6倍是\(threeTimesTable[6])") 你可以通过下标脚本来得到结果,比如`threeTimesTable[6]`。这条语句访问了`threeTimesTable`的第六个元素,返回`6`的`3`倍即`18`。 >注意: -> `TimesTable`例子是基于一个固定的数学公式。它并不适合开放写权限来对`threeTimesTable[someIndex]`进行赋值操作,这也是为什么附属脚本只定义为只读的原因。 +> `TimesTable`例子是基于一个固定的数学公式。它并不适合对`threeTimesTable[someIndex]`进行赋值操作,这也是为什么附属脚本只定义为只读的原因。 ## 下标脚本用法 @@ -77,7 +77,7 @@ var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] numberOfLegs["bird"] = 2 ``` -上例定义一个名为`numberOfLegs`的变量并用一个字典字面量初始化出了包含三对键值的字典实例。`numberOfLegs`的字典存放值类型推断为`Dictionary`。字典实例创建完成之后通过下标脚本的方式将整型值`2`赋值到字典实例的索引为`bird`的位置中。 +上例定义一个名为`numberOfLegs`的变量并用一个字典字面量初始化出了包含三对键值的字典实例。`numberOfLegs`的字典存放值类型推断为`[String:Int]`。字典实例创建完成之后通过下标脚本的方式将整型值`2`赋值到字典实例的索引为`bird`的位置中。 更多关于字典(Dictionary)下标脚本的信息请参考[读取和修改字典](../chapter2/04_Collection_Types.html) @@ -118,7 +118,7 @@ struct Matrix { } ``` -`Matrix`提供了一个两个入参的构造方法,入参分别是`rows`和`columns`,创建了一个足够容纳`rows * columns`个数的`Double`类型数组。为了存储,将数组的大小和数组每个元素初始值0.0,都传入数组的构造方法中来创建一个正确大小的新数组。关于数组的构造方法和析构方法请参考[创建并且构造一个数组](../chapter2/04_Collection_Types.html)。 +`Matrix`提供了一个两个入参的构造方法,入参分别是`rows`和`columns`,创建了一个足够容纳`rows * columns`个数的`Double`类型数组。通过传入数组长度和初始值0.0到数组的一个构造器,将`Matrix`中每个元素初始值0.0。关于数组的构造方法和析构方法请参考[创建并且构造一个数组](../chapter2/04_Collection_Types.html)。 你可以通过传入合适的`row`和`column`的数量来构造一个新的`Matrix`实例: @@ -151,7 +151,7 @@ matrix[1, 0] = 3.2 3.2, 0.0] ``` -`Matrix`下标脚本的`getter`和`setter`中同时调用了下标脚本入参的`row`和`column`是否有效的判断。为了方便进行断言,`Matrix`包含了一个名为`indexIsValid`的成员方法,用来确认入参的`row`或`column`值是否会造成数组越界: +`Matrix`下标脚本的`getter`和`setter`中同时调用了下标脚本入参的`row`和`column`是否有效的判断。为了方便进行断言,`Matrix`包含了一个名为`indexIsValidForRow(_:column:)`的成员方法,用来确认入参的`row`或`column`值是否会造成数组越界: ```swift func indexIsValidForRow(row: Int, column: Int) -> Bool { From 55ae3656be806f6ccbffce0764d7c628190b69ff Mon Sep 17 00:00:00 2001 From: chenYuheng Date: Tue, 30 Jun 2015 22:35:04 +0800 Subject: [PATCH 40/50] =?UTF-8?q?=E6=96=B0=E6=B7=BB=E5=8A=A0=E4=BA=86Exten?= =?UTF-8?q?ding=20a=20Generic=20Type=E5=B0=8F=E8=8A=82=E7=9A=84=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/23_Generics.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/source/chapter2/23_Generics.md b/source/chapter2/23_Generics.md index ec031e3e..d139812e 100644 --- a/source/chapter2/23_Generics.md +++ b/source/chapter2/23_Generics.md @@ -1,5 +1,5 @@ -> 翻译:[takalard](https://github.com/takalard) +> 翻译:[takalard](https://github.com/takalard) [SergioChan](https://github.com/SergioChan) > 校对:[lifedim](https://github.com/lifedim) # 泛型 @@ -13,6 +13,7 @@ - [类型参数](#type_parameters) - [命名类型参数](#naming_type_parameters) - [泛型类型](#generic_types) +- [扩展一个泛型类型](#extending_a_generic_type) - [类型约束](#type_constraints) - [关联类型](#associated_types) - [`Where`语句](#where_clauses) @@ -226,6 +227,33 @@ let fromTheTop = stackOfStrings.pop() 下图展示了如何从栈中pop一个值的过程: ![此处输入图片的描述](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/stackPoppedOneString_2x.png) + +## 扩展一个泛型类型 + +当你扩展一个泛型类型的时候,你并不需要在扩展的定义中提供类型参数列表。更加方便的是,原始类型定义中声明的类型参数列表在扩展里是可以使用的,并且这些来自原始类型中的参数名称会被用作原始定义中类型参数的引用。 + +下面的例子扩展了泛型`Stack`类型,为其添加了一个名为`topItem`的只读计算属性,它将会返回当前栈顶端的元素而不会将其从栈中移除。 + +```swift +extension Stack { + var topItem: T? { + return items.isEmpty ? nil : items[items.count - 1] + } +} +``` + +`topItem`属性会返回一个`T`类型的可选值。当栈为空的时候,`topItem`将会返回`nil`;当栈不为空的时候,`topItem`会返回`items`数组中的最后一个元素。 + +注意这里的扩展并没有定义一个类型参数列表。相反的,`Stack`类型已有的类型参数名称,`T`,被用在扩展中当做`topItem`计算属性的可选类型。 + +`topItem`计算属性现在可以被用来返回任意`Stack`实例的顶端元素而无需移除它: + +```swift +if let topItem = stackOfStrings.topItem { + print("The top item on the stack is \(topItem).") +} +// 打印 "The top item on the stack is tres." +``` ##类型约束 From 3e3fba64dce43dc4a1ed5dbfb3015580ee9de701 Mon Sep 17 00:00:00 2001 From: chenYuheng Date: Tue, 30 Jun 2015 22:50:24 +0800 Subject: [PATCH 41/50] =?UTF-8?q?=E5=AE=8C=E6=88=90Generic-Type=20Constrai?= =?UTF-8?q?nt=E5=B0=8F=E8=8A=82=E7=9A=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/23_Generics.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/source/chapter2/23_Generics.md b/source/chapter2/23_Generics.md index d139812e..c5c113af 100644 --- a/source/chapter2/23_Generics.md +++ b/source/chapter2/23_Generics.md @@ -43,7 +43,7 @@ func swapTwoInts(inout a: Int, inout _ b: Int) { var someInt = 3 var anotherInt = 107 swapTwoInts(&someInt, &anotherInt) -println("someInt is now \(someInt), and anotherInt is now \(anotherInt)") +print("someInt is now \(someInt), and anotherInt is now \(anotherInt)") // 输出 "someInt is now 107, and anotherInt is now 3" ``` @@ -252,13 +252,13 @@ extension Stack { if let topItem = stackOfStrings.topItem { print("The top item on the stack is \(topItem).") } -// 打印 "The top item on the stack is tres." +// 输出 "The top item on the stack is tres." ``` ##类型约束 -`swapTwoValues`函数和`Stack`类型可以作用于任何类型,不过,有的时候对使用在泛型函数和泛型类型上的类型强制约束为某种特定类型是非常有用的。类型约束指定了一个必须继承自指定类的类型参数,或者遵循一个特定的协议或协议构成。 +`swapTwoValues(_:_:)`函数和`Stack`类型可以作用于任何类型,不过,有的时候对使用在泛型函数和泛型类型上的类型强制约束为某种特定类型是非常有用的。类型约束指定了一个必须继承自指定类的类型参数,或者遵循一个特定的协议或协议构成。 例如,Swift 的`Dictionary`类型对作用于其键的类型做了些限制。在[字典](../chapter2/04_Collection_Types.html)的描述中,字典的键类型必须是*可哈希*,也就是说,必须有一种方法可以使其被唯一的表示。`Dictionary`之所以需要其键是可哈希是为了以便于其检查其是否已经包含某个特定键的值。如无此需求,`Dictionary`既不会告诉是否插入或者替换了某个特定键的值,也不能查找到已经存储在字典里面的给定键值。 @@ -272,7 +272,7 @@ if let topItem = stackOfStrings.topItem { ```swift func someFunction(someT: T, someU: U) { - // function body goes here + // 这里是函数主体 } ``` @@ -280,11 +280,11 @@ func someFunction(someT: T, someU: U) { ### 类型约束行为 -这里有个名为`findStringIndex`的非泛型函数,该函数功能是去查找包含一给定`String`值的数组。若查找到匹配的字符串,`findStringIndex`函数返回该字符串在数组中的索引值(`Int`),反之则返回`nil`: +这里有个名为`findStringIndex`的非泛型函数,该函数功能是去查找包含一给定`String`值的数组。若查找到匹配的字符串,`findStringIndex(_:_:)`函数返回该字符串在数组中的索引值(`Int`),反之则返回`nil`: ```swift -func findStringIndex(array: [String], valueToFind: String) -> Int? { - for (index, value) in enumerate(array) { +func findStringIndex(array: [String], _ valueToFind: String) -> Int? { + for (index, value) in array.enumerate() { if value == valueToFind { return index } @@ -294,12 +294,12 @@ func findStringIndex(array: [String], valueToFind: String) -> Int? { ``` -`findStringIndex`函数可以作用于查找一字符串数组中的某个字符串: +`findStringIndex(_:_:)`函数可以作用于查找一字符串数组中的某个字符串: ```swift let strings = ["cat", "dog", "llama", "parakeet", "terrapin"] if let foundIndex = findStringIndex(strings, "llama") { - println("The index of llama is \(foundIndex)") + print("The index of llama is \(foundIndex)") } // 输出 "The index of llama is 2" ``` @@ -309,8 +309,8 @@ if let foundIndex = findStringIndex(strings, "llama") { 这里展示如何写一个你或许期望的`findStringIndex`的泛型版本`findIndex`。请注意这个函数仍然返回`Int`,是不是有点迷惑呢,而不是泛型类型?那是因为函数返回的是一个可选的索引数,而不是从数组中得到的一个可选值。需要提醒的是,这个函数不会编译,原因在例子后面会说明: ```swift -func findIndex(array: [T], valueToFind: T) -> Int? { - for (index, value) in enumerate(array) { +func findIndex(array: [T], _ valueToFind: T) -> Int? { + for (index, value) in array.enumerate() { if value == valueToFind { return index } @@ -323,11 +323,11 @@ func findIndex(array: [T], valueToFind: T) -> Int? { 不过,所有的这些并不会让我们无从下手。Swift 标准库中定义了一个`Equatable`协议,该协议要求任何遵循的类型实现等式符(==)和不等符(!=)对任何两个该类型进行比较。所有的 Swift 标准类型自动支持`Equatable`协议。 -任何`Equatable`类型都可以安全的使用在`findIndex`函数中,因为其保证支持等式操作。为了说明这个事实,当你定义一个函数时,你可以写一个`Equatable`类型约束作为类型参数定义的一部分: +任何`Equatable`类型都可以安全的使用在`findIndex(_:_:)`函数中,因为其保证支持等式操作。为了说明这个事实,当你定义一个函数时,你可以写一个`Equatable`类型约束作为类型参数定义的一部分: ```swift -func findIndex(array: T[], valueToFind: T) -> Int? { - for (index, value) in enumerate(array) { +func findIndex(array: [T], _ valueToFind: T) -> Int? { + for (index, value) in array.enumerate() { if value == valueToFind { return index } @@ -339,7 +339,7 @@ func findIndex(array: T[], valueToFind: T) -> Int? { `findIndex`中这个单个类型参数写做:`T: Equatable`,也就意味着“任何T类型都遵循`Equatable`协议”。 -`findIndex`函数现在则可以成功的编译过,并且作用于任何遵循`Equatable`的类型,如`Double`或`String`: +`findIndex(_:_:)`函数现在则可以成功的编译过,并且作用于任何遵循`Equatable`的类型,如`Double`或`String`: ```swift let doubleIndex = findIndex([3.14159, 0.1, 0.25], 9.3) From 2380574b4e4d8685a605d223c9d0f12d60408c26 Mon Sep 17 00:00:00 2001 From: chenYuheng Date: Wed, 1 Jul 2015 00:02:17 +0800 Subject: [PATCH 42/50] =?UTF-8?q?=E5=AE=8C=E6=88=90Generics=E7=AB=A0?= =?UTF-8?q?=E8=8A=82=E7=9A=84=E4=BF=AE=E6=94=B9=E5=92=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/23_Generics.md | 46 +++++++++++++++++----------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/source/chapter2/23_Generics.md b/source/chapter2/23_Generics.md index c5c113af..2fa90bc5 100644 --- a/source/chapter2/23_Generics.md +++ b/source/chapter2/23_Generics.md @@ -355,7 +355,7 @@ let stringIndex = findIndex(["Mike", "Malcolm", "Andrea"], "Andrea") ### 关联类型行为 -这里是一个`Container`协议的例子,定义了一个ItemType关联类型: +这里是一个`Container`协议的例子,定义了一个`ItemType`关联类型: ```swift protocol Container { @@ -368,19 +368,19 @@ protocol Container { `Container`协议定义了三个任何容器必须支持的兼容要求: -- 必须可以通过`append`方法添加一个新item到容器里; -- 必须可以通过使用`count`属性获取容器里items的数量,并返回一个`Int`值; -- 必须可以通过容器的`Int`索引值下标可以检索到每一个item。 +- 必须可以通过`append(_:)`方法添加一个新元素到容器里; +- 必须可以通过使用`count`属性获取容器里元素的数量,并返回一个`Int`值; +- 必须可以通过容器的`Int`索引值下标可以检索到每一个元素。 -这个协议没有指定容器里item是如何存储的或何种类型是允许的。这个协议只指定三个任何遵循`Container`类型所必须支持的功能点。一个遵循的类型在满足这三个条件的情况下也可以提供其他额外的功能。 +这个协议没有指定容器里的元素是如何存储的或何种类型是允许的。这个协议只指定三个任何遵循`Container`类型所必须支持的功能点。一个遵循的类型在满足这三个条件的情况下也可以提供其他额外的功能。 -任何遵循`Container`协议的类型必须指定存储在其里面的值类型,必须保证只有正确类型的items可以加进容器里,必须明确可以通过其下标返回item类型。 +任何遵循`Container`协议的类型必须指定存储在其里面的值类型,必须保证只有正确类型的元素可以加进容器里,必须明确可以通过其下标返回元素类型。 -为了定义这三个条件,`Container`协议需要一个方法指定容器里的元素将会保留,而不需要知道特定容器的类型。`Container`协议需要指定任何通过`append`方法添加到容器里的值和容器里元素是相同类型,并且通过容器下标返回的容器元素类型的值的类型是相同类型。 +为了定义这三个条件,`Container`协议需要一个方法指定容器里的元素将会保留,而不需要知道特定容器的类型。`Container`协议需要指定任何通过`append(_:)`方法添加到容器里的值和容器里元素是相同类型,并且通过容器下标返回的容器元素类型的值的类型是相同类型。 -为了达到此目的,`Container`协议声明了一个ItemType的关联类型,写作`typealias ItemType`。这个协议不会定义`ItemType`是什么的别名,这个信息将由任何遵循协议的类型来提供。尽管如此,`ItemType`别名提供了一种识别Container中Items类型的方法,并且用于`append`方法和`subscript`方法的类型定义,以便保证任何`Container`期望的行为能够被执行。 +为了达到此目的,`Container`协议声明了一个`ItemType`的关联类型,写作`typealias ItemType`。这个协议不会定义`ItemType`是什么的别名,这个信息将由任何遵循协议的类型来提供。尽管如此,`ItemType`别名提供了一种识别`Container`中元素类型的方法,并且用于`append(_:)`方法和`subscript`方法的类型定义,以便保证任何`Container`期望的行为能够被执行。 -这里是一个早前IntStack类型的非泛型版本,遵循Container协议: +这里是一个早前`IntStack`类型的非泛型版本,遵循`Container`协议: ```swift struct IntStack: Container { @@ -398,7 +398,7 @@ struct IntStack: Container { self.push(item) } var count: Int { - return items.count + return items.count } subscript(i: Int) -> Int { return items[i] @@ -409,9 +409,9 @@ struct IntStack: Container { `IntStack`类型实现了`Container`协议的所有三个要求,在`IntStack`类型的每个包含部分的功能都满足这些要求。 -此外,`IntStack`指定了`Container`的实现,适用的ItemType被用作`Int`类型。对于这个`Container`协议实现而言,定义 `typealias ItemType = Int`,将抽象的`ItemType`类型转换为具体的`Int`类型。 +此外,`IntStack`指定了`Container`的实现,适用的`ItemType`被用作`Int`类型。对于这个`Container`协议实现而言,定义 `typealias ItemType = Int`,将抽象的`ItemType`类型转换为具体的`Int`类型。 -感谢Swift类型参考,你不用在`IntStack`定义部分声明一个具体的`Int`的`ItemType`。由于`IntStack`遵循`Container`协议的所有要求,只要通过简单的查找`append`方法的item参数类型和下标返回的类型,Swift就可以推断出合适的`ItemType`来使用。确实,如果上面的代码中你删除了 `typealias ItemType = Int`这一行,一切仍旧可以工作,因为它清楚的知道ItemType使用的是何种类型。 +感谢Swift类型参考,你不用在`IntStack`定义部分声明一个具体的`Int`的`ItemType`。由于`IntStack`遵循`Container`协议的所有要求,只要通过简单的查找`append(_:)`方法的`item`参数类型和下标返回的类型,Swift就可以推断出合适的`ItemType`来使用。确实,如果上面的代码中你删除了 `typealias ItemType = Int`这一行,一切仍旧可以工作,因为它清楚的知道`ItemType`使用的是何种类型。 你也可以生成遵循`Container`协议的泛型`Stack`类型: @@ -430,7 +430,7 @@ struct Stack: Container { self.push(item) } var count: Int { - return items.count + return items.count } subscript(i: Int) -> T { return items[i] @@ -438,20 +438,20 @@ struct Stack: Container { } ``` -这个时候,占位类型参数`T`被用作`append`方法的item参数和下标的返回类型。Swift 因此可以推断出被用作这个特定容器的`ItemType`的`T`的合适类型。 +这个时候,占位类型参数`T`被用作`append(_:)`方法的`item`参数和下标的返回类型。Swift 因此可以推断出被用作这个特定容器的`ItemType`的`T`的合适类型。 ### 扩展一个存在的类型为一指定关联类型 在[使用扩展来添加协议兼容性](../chapter2/21_Protocols.html)中有描述扩展一个存在的类型添加遵循一个协议。这个类型包含一个关联类型的协议。 -Swift的`Array`已经提供`append`方法,一个`count`属性和通过下标来查找一个自己的元素。这三个功能都达到`Container`协议的要求。也就意味着你可以扩展`Array`去遵循`Container`协议,只要通过简单声明`Array`适用于该协议而已。如何实践这样一个空扩展,在[使用扩展来声明协议的采纳](../chapter2/21_Protocols.html)中有描述这样一个实现一个空扩展的行为: +Swift的`Array`已经提供`append(_:)`方法,一个`count`属性和通过下标来查找一个自己的元素。这三个功能都达到`Container`协议的要求。也就意味着你可以扩展`Array`去遵循`Container`协议,只要通过简单声明`Array`适用于该协议而已。如何实践这样一个空扩展,在[使用扩展来声明协议的采纳](../chapter2/21_Protocols.html)中有描述这样一个实现一个空扩展的行为: ```swift extension Array: Container {} ``` -如同上面的泛型`Stack`类型一样,`Array的append`方法和下标保证`Swift`可以推断出`ItemType`所使用的适用的类型。定义了这个扩展后,你可以将任何`Array`当作`Container`来使用。 +如同上面的泛型`Stack`类型一样,`Array`的`append(_:)`方法和下标保证`Swift`可以推断出`ItemType`所使用的适用的类型。定义了这个扩展后,你可以将任何`Array`当作`Container`来使用。 ## Where 语句 @@ -509,15 +509,15 @@ func allItemsMatch< 第三个和第四个要求结合起来的意思是`anotherContainer`中的元素也可以通过 `!=` 操作来检查,因为它们在`someContainer`中元素确实是相同的类型。 -这些要求能够使`allItemsMatch`函数比较两个容器,即便它们是不同的容器类型。 +这些要求能够使`allItemsMatch(_:_:)`函数比较两个容器,即便它们是不同的容器类型。 -`allItemsMatch`首先检查两个容器是否拥有同样数目的items,如果它们的元素数目不同,没有办法进行匹配,函数就会`false`。 +`allItemsMatch(_:_:)`首先检查两个容器是否拥有同样数目的items,如果它们的元素数目不同,没有办法进行匹配,函数就会`false`。 -检查完之后,函数通过`for-in`循环和半闭区间操作(..)来迭代`someContainer`中的所有元素。对于每个元素,函数检查是否`someContainer`中的元素不等于对应的`anotherContainer`中的元素,如果这两个元素不等,则这两个容器不匹配,返回`false`。 +检查完之后,函数通过`for-in`循环和半闭区间操作(`..<`)来迭代`someContainer`中的所有元素。对于每个元素,函数检查是否`someContainer`中的元素不等于对应的`anotherContainer`中的元素,如果这两个元素不等,则这两个容器不匹配,返回`false`。 如果循环体结束后未发现没有任何的不匹配,那表明两个容器匹配,函数返回`true`。 -这里演示了allItemsMatch函数运算的过程: +这里演示了`allItemsMatch(_:_:)`函数运算的过程: ```swift var stackOfStrings = Stack() @@ -528,14 +528,14 @@ stackOfStrings.push("tres") var arrayOfStrings = ["uno", "dos", "tres"] if allItemsMatch(stackOfStrings, arrayOfStrings) { - println("All items match.") + print("All items match.") } else { - println("Not all items match.") + print("Not all items match.") } // 输出 "All items match." ``` - 上面的例子创建一个`Stack`单例来存储`String`,然后压了三个字符串进栈。这个例子也创建了一个`Array`单例,并初始化包含三个同栈里一样的原始字符串。即便栈和数组是不同的类型,但它们都遵循`Container`协议,而且它们都包含同样的类型值。因此你可以调用`allItemsMatch`函数,用这两个容器作为它的参数。在上面的例子中,`allItemsMatch`函数正确的显示了所有的这两个容器的`items`匹配。 + 上面的例子创建一个`Stack`单例来存储`String`,然后压了三个字符串进栈。这个例子也创建了一个`Array`单例,并初始化包含三个同栈里一样的原始字符串。即便栈和数组是不同的类型,但它们都遵循`Container`协议,而且它们都包含同样的类型值。因此你可以调用`allItemsMatch(_:_:)`函数,用这两个容器作为它的参数。在上面的例子中,`allItemsMatch(_:_:)`函数正确的显示了这两个容器的所有元素都是相互匹配的。 [1]: ../chapter2/06_Functions.html [2]: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/stackPushPop_2x.png From 03fb94ea6dc3530c2d6233139e96f9239b730081 Mon Sep 17 00:00:00 2001 From: Siyu Yang Date: Tue, 30 Jun 2015 21:02:54 +0800 Subject: [PATCH 43/50] Chapter2_Properties Section1_Stored_Properties finished --- source/chapter2/10_Properties.md | 42 +++++++++++++++++--------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/source/chapter2/10_Properties.md b/source/chapter2/10_Properties.md index bf305032..4070c1c2 100755 --- a/source/chapter2/10_Properties.md +++ b/source/chapter2/10_Properties.md @@ -1,5 +1,5 @@ > 翻译:[shinyzhu](https://github.com/shinyzhu) -> 校对:[pp-prog](https://github.com/pp-prog) +> 校对:[pp-prog](https://github.com/pp-prog) [yangsiy](https://github.com/yangsiy) # 属性 (Properties) --- @@ -12,16 +12,16 @@ - [全局变量和局部变量(Global and Local Variables)](#global_and_local_variables) - [类型属性(Type Properties)](#type_properties) -**属性**将值跟特定的类、结构或枚举关联。存储属性存储常量或变量作为实例的一部分,计算属性计算(而不是存储)一个值。计算属性可以用于类、结构体和枚举里,存储属性只能用于类和结构体。 +*属性*将值跟特定的类、结构或枚举关联。存储属性存储常量或变量作为实例的一部分,而计算属性计算(不是存储)一个值。计算属性可以用于类、结构体和枚举,存储属性只能用于类和结构体。 -存储属性和计算属性通常用于特定类型的实例,但是,属性也可以直接用于类型本身,这种属性称为类型属性。 +存储属性和计算属性通常与特定类型的实例关联。但是,属性也可以直接作用于类型本身,这种属性称为类型属性。 -另外,还可以定义属性观察器来监控属性值的变化,以此来触发一个自定义的操作。属性观察器可以添加到自己写的存储属性上,也可以添加到从父类继承的属性上。 +另外,还可以定义属性观察器来监控属性值的变化,以此来触发一个自定义的操作。属性观察器可以添加到自己定义的存储属性上,也可以添加到从父类继承的属性上。 ## 存储属性 -简单来说,一个存储属性就是存储在特定类或结构体的实例里的一个常量或变量,存储属性可以是*变量存储属性*(用关键字`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)一节。 @@ -38,12 +38,12 @@ rangeOfThreeItems.firstValue = 6 // 该区间现在表示整数6,7,8 ``` -`FixedLengthRange`的实例包含一个名为`firstValue`的变量存储属性和一个名为`length`的常量存储属性。在上面的例子中,`length`在创建实例的时候被赋值,因为它是一个常量存储属性,所以之后无法修改它的值。 +`FixedLengthRange`的实例包含一个名为`firstValue`的变量存储属性和一个名为`length`的常量存储属性。在上面的例子中,`length`在创建实例的时候被初始化,因为它是一个常量存储属性,所以之后无法修改它的值。 -### 常量和存储属性 +### 常量结构体的存储属性 -如果创建了一个结构体的实例并赋值给一个常量,则无法修改实例的任何属性,即使定义了变量存储属性: +如果创建了一个结构体的实例并将其赋值给一个常量,则无法修改该实例的任何属性,即使定义了变量存储属性: ```swift let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4) @@ -52,11 +52,11 @@ rangeOfFourItems.firstValue = 6 // 尽管 firstValue 是个变量属性,这里还是会报错 ``` -因为`rangeOfFourItems`声明成了常量(用`let`关键字),即使`firstValue`是一个变量属性,也无法再修改它了。 +因为`rangeOfFourItems`被声明成了常量(用`let`关键字),即使`firstValue`是一个变量属性,也无法再修改它了。 这种行为是由于结构体(struct)属于*值类型*。当值类型的实例被声明为常量的时候,它的所有属性也就成了常量。 -属于*引用类型*的类(class)则不一样,把一个引用类型的实例赋给一个常量后,仍然可以修改实例的变量属性。 +属于*引用类型*的类(class)则不一样。把一个引用类型的实例赋给一个常量后,仍然可以修改该实例的变量属性。 ### 延迟存储属性 @@ -64,11 +64,11 @@ rangeOfFourItems.firstValue = 6 延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用`lazy`来标示一个延迟存储属性。 > 注意: -> 必须将延迟存储属性声明成变量(使用`var`关键字),因为属性的值在实例构造完成之前可能无法得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。 +> 必须将延迟存储属性声明成变量(使用`var`关键字),因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。 -延迟属性很有用,当属性的值依赖于在实例的构造过程结束前无法知道具体值的外部因素时,或者当属性的值需要复杂或大量计算时,可以只在需要的时候来计算它。 +延迟属性很有用,当属性的值依赖于在实例的构造过程结束后才会知道具体值的外部因素时,或者当获得属性的初始值需要复杂或大量计算时,可以只在需要的时候计算它。 -下面的例子使用了延迟存储属性来避免复杂类的不必要的初始化。例子中定义了`DataImporter`和`DataManager`两个类,下面是部分代码: +下面的例子使用了延迟存储属性来避免复杂类中不必要的初始化。例子中定义了`DataImporter`和`DataManager`两个类,下面是部分代码: ```swift class DataImporter { @@ -94,25 +94,27 @@ manager.data.append("Some more data") `DataManager`类包含一个名为`data`的存储属性,初始值是一个空的字符串(`String`)数组。虽然没有写出全部代码,`DataManager`类的目的是管理和提供对这个字符串数组的访问。 -`DataManager`的一个功能是从文件导入数据,该功能由`DataImporter`类提供,`DataImporter`需要消耗不少时间完成初始化:因为它的实例在初始化时可能要打开文件,还要读取文件内容到内存。 +`DataManager`的一个功能是从文件导入数据。该功能由`DataImporter`类提供,`DataImporter`完成初始化需要消耗不少时间:因为它的实例在初始化时可能要打开文件,还要读取文件内容到内存。 -`DataManager`也可能不从文件中导入数据。所以当`DataManager`的实例被创建时,没必要创建一个`DataImporter`的实例,更明智的是当用到`DataImporter`的时候才去创建它。 +`DataManager`也可能不从文件中导入数据就完成了管理数据的功能。所以当`DataManager`的实例被创建时,没必要创建一个`DataImporter`的实例,更明智的是当第一次用到`DataImporter`的时候才去创建它。 由于使用了`lazy`,`importer`属性只有在第一次被访问的时候才被创建。比如访问它的属性`fileName`时: ```swift -println(manager.importer.fileName) +print(manager.importer.fileName) // DataImporter 实例的 importer 属性现在被创建了 // 输出 "data.txt” -``` +``` + +> 注意: +> 如果一个被标记为`lazy`的属性在没有初始化时就同时被多个线程访问,则无法保证该属性只会被初始化一次。 ### 存储属性和实例变量 -如果您有过 Objective-C 经验,应该知道Objective-C为类实例存储值和引用提供两种方法。对于属性来说,也可以使用实例变量作为属性值的后端存储。 +如果您有过 Objective-C 经验,应该知道 Objective-C 为类实例存储值和引用提供两种方法。对于属性来说,也可以使用实例变量作为属性值的后端存储。 -Swift 编程语言中把这些理论统一用属性来实现。Swift 中的属性没有对应的实例变量,属性的后端存储也无法直接访问。这就避免了不同场景下访问方式的困扰,同时也将属性的定义简化成一个语句。 -一个类型中属性的全部信息——包括命名、类型和内存管理特征——都在唯一一个地方(类型定义中)定义。 +Swift 编程语言中把这些理论统一用属性来实现。Swift 中的属性没有对应的实例变量,属性的后端存储也无法直接访问。这就避免了不同场景下访问方式的困扰,同时也将属性的定义简化成一个语句。一个类型中属性的全部信息——包括命名、类型和内存管理特征——都在唯一一个地方(类型定义中)定义。 ## 计算属性 From 1c9b0ceae795d53130c64b1a364b90053e766750 Mon Sep 17 00:00:00 2001 From: Siyu Yang Date: Tue, 30 Jun 2015 22:14:26 +0800 Subject: [PATCH 44/50] Chapter2_Properties Section2_Computed_Properties finished --- source/chapter2/10_Properties.md | 62 ++++++++++++++++---------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/source/chapter2/10_Properties.md b/source/chapter2/10_Properties.md index 4070c1c2..4e645540 100755 --- a/source/chapter2/10_Properties.md +++ b/source/chapter2/10_Properties.md @@ -119,7 +119,7 @@ Swift 编程语言中把这些理论统一用属性来实现。Swift 中的属 ## 计算属性 -除存储属性外,类、结构体和枚举可以定义*计算属性*,计算属性不直接存储值,而是提供一个 getter 来获取值,一个可选的 setter 来间接设置其他属性或变量的值。 +除存储属性外,类、结构体和枚举可以定义*计算属性*。计算属性不直接存储值,而是提供一个 getter 和一个可选的 setter,来间接获取和设置其他属性或变量的值。 ```swift struct Point { @@ -132,38 +132,38 @@ struct Rect { var origin = Point() var size = Size() var center: Point { - get { - let centerX = origin.x + (size.width / 2) - let centerY = origin.y + (size.height / 2) - return Point(x: centerX, y: centerY) - } - set(newCenter) { - origin.x = newCenter.x - (size.width / 2) - origin.y = newCenter.y - (size.height / 2) - } + get { + let centerX = origin.x + (size.width / 2) + let centerY = origin.y + (size.height / 2) + return Point(x: centerX, y: centerY) + } + set(newCenter) { + origin.x = newCenter.x - (size.width / 2) + origin.y = newCenter.y - (size.height / 2) + } } } var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0)) let initialSquareCenter = square.center square.center = Point(x: 15.0, y: 15.0) -println("square.origin is now at (\(square.origin.x), \(square.origin.y))") +print("square.origin is now at (\(square.origin.x), \(square.origin.y))") // 输出 "square.origin is now at (10.0, 10.0)” ``` -这个例子定义了 3 个几何形状的结构体: +这个例子定义了 3 个结构体来描述几何形状: - `Point`封装了一个`(x, y)`的坐标 -- `Size`封装了一个`width`和`height` +- `Size`封装了一个`width`和一个`height` - `Rect`表示一个有原点和尺寸的矩形 -`Rect`也提供了一个名为`center`的计算属性。一个矩形的中心点可以从原点和尺寸来算出,所以不需要将它以显式声明的`Point`来保存。`Rect`的计算属性`center`提供了自定义的 getter 和 setter 来获取和设置矩形的中心点,就像它有一个存储属性一样。 +`Rect`也提供了一个名为`center`的计算属性。一个矩形的中心点可以从原点(`origin`)和尺寸(`size`)算出,所以不需要将它以显式声明的`Point`来保存。`Rect`的计算属性`center`提供了自定义的 getter 和 setter 来获取和设置矩形的中心点,就像它有一个存储属性一样。 -例子中接下来创建了一个名为`square`的`Rect`实例,初始值原点是`(0, 0)`,宽度高度都是`10`。如图所示蓝色正方形。 +上述例子中创建了一个名为`square`的`Rect`实例,初始值原点是`(0, 0)`,宽度高度都是`10`。如下图中蓝色正方形所示。 -`square`的`center`属性可以通过点运算符(`square.center`)来访问,这会调用 getter 来获取属性的值。跟直接返回已经存在的值不同,getter 实际上通过计算然后返回一个新的`Point`来表示`square`的中心点。如代码所示,它正确返回了中心点`(5, 5)`。 +`square`的`center`属性可以通过点运算符(`square.center`)来访问,这会调用该属性的 getter 来获取它的值。跟直接返回已经存在的值不同,getter 实际上通过计算然后返回一个新的`Point`来表示`square`的中心点。如代码所示,它正确返回了中心点`(5, 5)`。 -`center`属性之后被设置了一个新的值`(15, 15)`,表示向右上方移动正方形到如图所示橙色正方形的位置。设置属性`center`的值会调用 setter 来修改属性`origin`的`x`和`y`的值,从而实现移动正方形到新的位置。 +`center`属性之后被设置了一个新的值`(15, 15)`,表示向右上方移动正方形到如下图橙色正方形所示的位置。设置属性`center`的值会调用它的 setter 来修改属性`origin`的`x`和`y`的值,从而实现移动正方形到新的位置。 Computed Properties sample @@ -177,15 +177,15 @@ struct AlternativeRect { var origin = Point() var size = Size() var center: Point { - get { - let centerX = origin.x + (size.width / 2) - let centerY = origin.y + (size.height / 2) - return Point(x: centerX, y: centerY) - } - set { - origin.x = newValue.x - (size.width / 2) - origin.y = newValue.y - (size.height / 2) - } + get { + let centerX = origin.x + (size.width / 2) + let centerY = origin.y + (size.height / 2) + return Point(x: centerX, y: centerY) + } + set { + origin.x = newValue.x - (size.width / 2) + origin.y = newValue.y - (size.height / 2) + } } } ``` @@ -195,26 +195,24 @@ struct AlternativeRect { 只有 getter 没有 setter 的计算属性就是*只读计算属性*。只读计算属性总是返回一个值,可以通过点运算符访问,但不能设置新的值。 -> 注意: -> +> 注意: > 必须使用`var`关键字定义计算属性,包括只读计算属性,因为它们的值不是固定的。`let`关键字只用来声明常量属性,表示初始化后再也无法修改的值。 - 只读计算属性的声明可以去掉`get`关键字和花括号: ```swift struct Cuboid { var width = 0.0, height = 0.0, depth = 0.0 var volume: Double { - return width * height * depth + return width * height * depth } } let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0) -println("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)") +print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)") // 输出 "the volume of fourByFiveByTwo is 40.0" ``` -这个例子定义了一个名为`Cuboid`的结构体,表示三维空间的立方体,包含`width`、`height`和`depth`属性,还有一个名为`volume`的只读计算属性用来返回立方体的体积。设置`volume`的值毫无意义,因为通过`width`、`height`和`depth`就能算出`volume`。然而,`Cuboid`提供一个只读计算属性来让外部用户直接获取体积是很有用的。 +这个例子定义了一个名为`Cuboid`的结构体,表示三维空间的立方体,包含`width`、`height`和`depth`属性。结构体还有一个名为`volume`的只读计算属性用来返回立方体的体积。设置`volume`的值毫无意义,因为无法确定修改`width`、`height`和`depth`三者中的哪些值来匹配新的`volume`,从而造成歧义。然而,`Cuboid`提供一个只读计算属性来让外部用户直接获取体积是很有用的。 ## 属性观察器 From 44f55a7a860abee52f81980f6c5d2615daccf6ab Mon Sep 17 00:00:00 2001 From: Siyu Yang Date: Wed, 1 Jul 2015 10:35:21 +0800 Subject: [PATCH 45/50] Chapter2_Properties Section3_Property_Observers finished --- source/chapter2/10_Properties.md | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/source/chapter2/10_Properties.md b/source/chapter2/10_Properties.md index 4e645540..43e53c0c 100755 --- a/source/chapter2/10_Properties.md +++ b/source/chapter2/10_Properties.md @@ -222,34 +222,33 @@ print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)") 可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重载属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。属性重载请参考[继承](chapter/13_Inheritance.html)一章的[重载](chapter/13_Inheritance.html#overriding)。 > 注意: -> 不需要为无法重载的计算属性添加属性观察器,因为可以通过 setter 直接监控和响应值的变化。 +> 不需要为非重载的计算属性添加属性观察器,因为可以通过它的 setter 直接监控和响应值的变化。 可以为属性添加如下的一个或全部观察器: -- `willSet`在设置新的值之前调用 +- `willSet`在新的值被设置之前调用 - `didSet`在新的值被设置之后立即调用 -`willSet`观察器会将新的属性值作为固定参数传入,在`willSet`的实现代码中可以为这个参数指定一个名称,如果不指定则参数仍然可用,这时使用默认名称`newValue`表示。 +`willSet`观察器会将新的属性值作为常量参数传入,在`willSet`的实现代码中可以为这个参数指定一个名称,如果不指定则参数仍然可用,这时使用默认名称`newValue`表示。 类似地,`didSet`观察器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名`oldValue`。 -> 注意: -> +> 注意: > `willSet`和`didSet`观察器在属性初始化过程中不会被调用,它们只会当属性的值在初始化之外的地方被设置时被调用。 -这里是一个`willSet`和`didSet`的实际例子,其中定义了一个名为`StepCounter`的类,用来统计当人步行时的总步数,可以跟计步器或其他日常锻炼的统计装置的输入数据配合使用。 +这里是一个`willSet`和`didSet`的实际例子,其中定义了一个名为`StepCounter`的类,用来统计当人步行时的总步数。这个类可以跟计步器或其他日常锻炼的统计装置的输入数据配合使用。 ```swift class StepCounter { var totalSteps: Int = 0 { - willSet(newTotalSteps) { - println("About to set totalSteps to \(newTotalSteps)") - } - didSet { - if totalSteps > oldValue { - println("Added \(totalSteps - oldValue) steps") + willSet(newTotalSteps) { + print("About to set totalSteps to \(newTotalSteps)") + } + didSet { + if totalSteps > oldValue { + print("Added \(totalSteps - oldValue) steps") + } } - } } } let stepCounter = StepCounter() @@ -270,10 +269,10 @@ stepCounter.totalSteps = 896 例子中的`willSet`观察器将表示新值的参数自定义为`newTotalSteps`,这个观察器只是简单的将新的值输出。 -`didSet`观察器在`totalSteps`的值改变后被调用,它把新的值和旧的值进行对比,如果总的步数增加了,就输出一个消息表示增加了多少步。`didSet`没有提供自定义名称,所以默认值`oldValue`表示旧值的参数名。 +`didSet`观察器在`totalSteps`的值改变后被调用,它把新的值和旧的值进行对比,如果总的步数增加了,就输出一个消息表示增加了多少步。`didSet`没有为旧的值提供自定义名称,所以默认值`oldValue`表示旧值的参数名。 > 注意: -> 如果在`didSet`观察器里为属性赋值,这个值会替换观察器之前设置的值。 +> 如果在一个属性的`didSet`观察器里为它赋值,这个值会替换该观察器之前设置的值。 ##全局变量和局部变量 From 2779cda3e9eff07d8f9159fb57b7eabc5bf0ccf4 Mon Sep 17 00:00:00 2001 From: Siyu Yang Date: Wed, 1 Jul 2015 15:56:14 +0800 Subject: [PATCH 46/50] Chapter2_Properties Section4&5 finished --- source/chapter2/10_Properties.md | 77 +++++++++++++++++--------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/source/chapter2/10_Properties.md b/source/chapter2/10_Properties.md index 43e53c0c..12f80f0b 100755 --- a/source/chapter2/10_Properties.md +++ b/source/chapter2/10_Properties.md @@ -277,11 +277,11 @@ stepCounter.totalSteps = 896 ##全局变量和局部变量 -计算属性和属性观察器所描述的模式也可以用于*全局变量*和*局部变量*,全局变量是在函数、方法、闭包或任何类型之外定义的变量,局部变量是在函数、方法或闭包内部定义的变量。 +计算属性和属性观察器所描述的模式也可以用于*全局变量*和*局部变量*。全局变量是在函数、方法、闭包或任何类型之外定义的变量。局部变量是在函数、方法或闭包内部定义的变量。 前面章节提到的全局或局部变量都属于存储型变量,跟存储属性类似,它提供特定类型的存储空间,并允许读取和写入。 -另外,在全局或局部范围都可以定义计算型变量和为存储型变量定义观察器,计算型变量跟计算属性一样,返回一个计算的值而不是存储值,声明格式也完全一样。 +另外,在全局或局部范围都可以定义计算型变量和为存储型变量定义观察器。计算型变量跟计算属性一样,返回一个计算的值而不是存储值,声明格式也完全一样。 > 注意: > 全局的常量或变量都是延迟计算的,跟[延迟存储属性](#lazy_stored_properties)相似,不同的地方在于,全局的常量或变量不需要标记`lazy`特性。 @@ -296,9 +296,7 @@ stepCounter.totalSteps = 896 类型属性用于定义特定类型所有实例共享的数据,比如所有实例都能用的一个常量(就像 C 语言中的静态常量),或者所有实例都能访问的一个变量(就像 C 语言中的静态变量)。 -对于值类型(指结构体和枚举)可以定义存储型和计算型类型属性,对于类(class)则只能定义计算型类型属性。 - -值类型的存储型类型属性可以是变量或常量,计算型类型属性跟实例的计算属性一样定义成变量属性。 +值类型的存储型类型属性可以是变量或常量,计算型类型属性跟实例的计算属性一样只能定义成变量属性。 > 注意: > 跟实例的存储属性不同,必须给存储型类型属性指定默认值,因为类型本身无法在初始化过程中使用构造器给类型属性赋值。 @@ -306,26 +304,30 @@ stepCounter.totalSteps = 896 ###类型属性语法 -在 C 或 Objective-C 中,静态常量和静态变量的定义是通过特定类型加上`global`关键字。在 Swift 编程语言中,类型属性是作为类型定义的一部分写在类型最外层的花括号内,因此它的作用范围也就在类型支持的范围内。 +在 C 或 Objective-C 中,与某个类型关联的静态常量和静态变量,是作为全局(*global*)静态变量定义的。但是在 Swift 编程语言中,类型属性是作为类型定义的一部分写在类型最外层的花括号内,因此它的作用范围也就在类型支持的范围内。 -使用关键字`static`来定义值类型的类型属性,关键字`class`来为类(class)定义类型属性。下面的例子演示了存储型和计算型类型属性的语法: +使用关键字`static`来定义类型属性。在为类(class)定义计算型类型属性时,可以使用关键字`class`来支持子类对父类的实现进行重写。下面的例子演示了存储型和计算型类型属性的语法: ```swift struct SomeStructure { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { - // 这里返回一个 Int 值 + return 1 } } enum SomeEnumeration { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { - // 这里返回一个 Int 值 + return 6 } } -class SomeClass { - class var computedTypeProperty: Int { - // 这里返回一个 Int 值 +class SomeClass { + static var storedTypeProperty = "Some value." + static var computedTypeProperty: Int { + return 27 + } + class var overrideableComputedTypeProperty: Int { + return 107 } } ``` @@ -336,17 +338,18 @@ class SomeClass { ###获取和设置类型属性的值 -跟实例的属性一样,类型属性的访问也是通过点运算符来进行,但是,类型属性是通过类型本身来获取和设置,而不是通过实例。比如: +跟实例的属性一样,类型属性的访问也是通过点运算符来进行。但是,类型属性是通过类型本身来获取和设置,而不是通过实例。比如: -```swift -println(SomeClass.computedTypeProperty) -// 输出 "42" - -println(SomeStructure.storedTypeProperty) -// 输出 "Some value." +```swift +print(SomeStructure.storedTypeProperty) +// 输出 "Some value." SomeStructure.storedTypeProperty = "Another value." -println(SomeStructure.storedTypeProperty) -// 输出 "Another value.” +print(SomeStructure.storedTypeProperty) +// 输出 "Another value.” +print(SomeEnumeration.computedTypeProperty) +// 输出 "6" +print(SomeClass.computedTypeProperty) +// 输出 "27" ``` 下面的例子定义了一个结构体,使用两个存储型类型属性来表示多个声道的声音电平值,每个声道有一个 0 到 10 之间的整数表示声音电平值。 @@ -355,23 +358,23 @@ println(SomeStructure.storedTypeProperty) Static Properties VUMeter -上面所描述的声道模型使用`AudioChannel`结构体来表示: +上面所描述的声道模型使用`AudioChannel`结构体的实例来表示: ```swift struct AudioChannel { static let thresholdLevel = 10 static var maxInputLevelForAllChannels = 0 var currentLevel: Int = 0 { - didSet { - if currentLevel > AudioChannel.thresholdLevel { - // 将新电平值设置为阀值 - currentLevel = AudioChannel.thresholdLevel + didSet { + if currentLevel > AudioChannel.thresholdLevel { + // 将新电平值设置为阀值 + currentLevel = AudioChannel.thresholdLevel + } + if currentLevel > AudioChannel.maxInputLevelForAllChannels { + // 存储当前电平值作为新的最大输入电平 + AudioChannel.maxInputLevelForAllChannels = currentLevel + } } - if currentLevel > AudioChannel.maxInputLevelForAllChannels { - // 存储当前电平值作为新的最大输入电平 - AudioChannel.maxInputLevelForAllChannels = currentLevel - } - } } } ``` @@ -382,10 +385,10 @@ struct AudioChannel { `AudioChannel`也定义了一个名为`currentLevel`的实例存储属性,表示当前声道现在的电平值,取值为 0 到 10。 -属性`currentLevel`包含`didSet`属性观察器来检查每次新设置后的属性值,有如下两个检查: +属性`currentLevel`包含`didSet`属性观察器来检查每次新设置后的属性值,它有如下两个检查: - 如果`currentLevel`的新值大于允许的阈值`thresholdLevel`,属性观察器将`currentLevel`的值限定为阈值`thresholdLevel`。 -- 如果修正后的`currentLevel`值大于任何之前任意`AudioChannel`实例中的值,属性观察器将新值保存在静态属性`maxInputLevelForAllChannels`中。 +- 如果前一个修正后的`currentLevel`值大于任何之前任意`AudioChannel`实例中的值,属性观察器将新值保存在静态类型属性`maxInputLevelForAllChannels`中。 > 注意: > 在第一个检查过程中,`didSet`属性观察器将`currentLevel`设置成了不同的值,但这时不会再次调用属性观察器。 @@ -401,9 +404,9 @@ var rightChannel = AudioChannel() ```swift leftChannel.currentLevel = 7 -println(leftChannel.currentLevel) +print(leftChannel.currentLevel) // 输出 "7" -println(AudioChannel.maxInputLevelForAllChannels) +print(AudioChannel.maxInputLevelForAllChannels) // 输出 "7" ``` @@ -411,8 +414,8 @@ println(AudioChannel.maxInputLevelForAllChannels) ```swift rightChannel.currentLevel = 11 -println(rightChannel.currentLevel) +print(rightChannel.currentLevel) // 输出 "10" -println(AudioChannel.maxInputLevelForAllChannels) +print(AudioChannel.maxInputLevelForAllChannels) // 输出 "10" ``` From 5ff10629b56f82ebc8833d305fe5e648b2203e02 Mon Sep 17 00:00:00 2001 From: Siyu Yang Date: Wed, 1 Jul 2015 16:32:30 +0800 Subject: [PATCH 47/50] Chapter2_Properties Section3 minor_fix --- source/chapter2/10_Properties.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/chapter2/10_Properties.md b/source/chapter2/10_Properties.md index 12f80f0b..3ee6921e 100755 --- a/source/chapter2/10_Properties.md +++ b/source/chapter2/10_Properties.md @@ -233,8 +233,9 @@ print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)") 类似地,`didSet`观察器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名`oldValue`。 -> 注意: -> `willSet`和`didSet`观察器在属性初始化过程中不会被调用,它们只会当属性的值在初始化之外的地方被设置时被调用。 +> 注意: +> 父类的属性在子类的构造器中被赋值时,它在父类中的`willSet`和`didSet`观察器会被调用。 +> 有关构造器代理的更多信息,请参考[值类型的构造器代理](chapter/14_Initialization.html#initializer_delegation_for_value_types)和[构造器链](chapter/14_Initialization.html#initialization_chain)。 这里是一个`willSet`和`didSet`的实际例子,其中定义了一个名为`StepCounter`的类,用来统计当人步行时的总步数。这个类可以跟计步器或其他日常锻炼的统计装置的输入数据配合使用。 From 39d551ae824fa292952e8d345b1a2a11ef68d0d7 Mon Sep 17 00:00:00 2001 From: Siyu Yang Date: Wed, 1 Jul 2015 16:35:59 +0800 Subject: [PATCH 48/50] Chapter2_Type_Casting quote_format minor_fix --- source/chapter2/20_Type_Casting.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/source/chapter2/20_Type_Casting.md b/source/chapter2/20_Type_Casting.md index dc72a95f..83929634 100644 --- a/source/chapter2/20_Type_Casting.md +++ b/source/chapter2/20_Type_Casting.md @@ -141,9 +141,8 @@ for item in library { 若向下转型成功,然后 `movie` 的属性将用于打印一个 `Movie` 实例的描述,包括它的导演的名字 `director` 。相近的原理被用来检测 `Song` 实例,当 `Song` 被找到时则打印它的描述(包含 `artist` 的名字)。 -> 注意: - ->转换没有真的改变实例或它的值。潜在的根本的实例保持不变;只是简单地把它作为它被转换成的类来使用。 +> 注意: +> 转换没有真的改变实例或它的值。潜在的根本的实例保持不变;只是简单地把它作为它被转换成的类来使用。 ## `Any`和`AnyObject`的类型转换 @@ -153,9 +152,8 @@ Swift为不确定类型提供了两种特殊类型别名: * `AnyObject`可以代表任何class类型的实例。 * `Any`可以表示任何类型,包括方法类型(function types)。 -> 注意: - ->只有当你明确的需要它的行为和功能时才使用`Any`和`AnyObject`。在你的代码里使用你期望的明确的类型总是更好的。 +> 注意: +> 只有当你明确的需要它的行为和功能时才使用`Any`和`AnyObject`。在你的代码里使用你期望的明确的类型总是更好的。 ### `AnyObject`类型 @@ -254,6 +252,5 @@ for thing in things { ``` -> 注意: - ->在一个switch语句的case中使用强制形式的类型转换操作符(as, 而不是 as?)来检查和转换到一个明确的类型。在 `switch` case 语句的内容中这种检查总是安全的。 +> 注意: +> 在一个switch语句的case中使用强制形式的类型转换操作符(as, 而不是 as?)来检查和转换到一个明确的类型。在 `switch` case 语句的内容中这种检查总是安全的。 From aee32488e24d7688817ef3bc538b0167a9ce469f Mon Sep 17 00:00:00 2001 From: chenYuheng Date: Wed, 1 Jul 2015 21:44:44 +0800 Subject: [PATCH 49/50] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E5=A4=84print?= =?UTF-8?q?ln=E7=9A=84=E6=9B=B4=E6=96=B0=EF=BC=8C=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E5=B5=8C=E5=A5=97=E7=B1=BB=E5=9E=8B=E7=9A=84=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=92=8C=E6=9B=B4=E6=96=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/19_Nested_Types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/chapter2/19_Nested_Types.md b/source/chapter2/19_Nested_Types.md index bd03302e..46c4a6bc 100755 --- a/source/chapter2/19_Nested_Types.md +++ b/source/chapter2/19_Nested_Types.md @@ -76,7 +76,7 @@ struct BlackjackCard { ```swift let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades) -println("theAceOfSpades: \(theAceOfSpades.description)") +print("theAceOfSpades: \(theAceOfSpades.description)") // 打印出 "theAceOfSpades: suit is ♠, value is 1 or 11" ``` From f12bd074fd4c792fb6bd1c8d933ed60684a4038d Mon Sep 17 00:00:00 2001 From: shanksyang Date: Thu, 2 Jul 2015 20:20:44 +0800 Subject: [PATCH 50/50] =?UTF-8?q?swift=202.0,=2013=5FInheritance,=E7=BB=A7?= =?UTF-8?q?=E6=89=BF=E9=83=A8=E5=88=86=E6=A0=A1=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/chapter2/13_Inheritance.md | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/source/chapter2/13_Inheritance.md b/source/chapter2/13_Inheritance.md index 3ab4e7a4..fc2f5918 100755 --- a/source/chapter2/13_Inheritance.md +++ b/source/chapter2/13_Inheritance.md @@ -11,11 +11,11 @@ - [重写(Overriding)](#overriding) - [防止重写](#preventing_overrides) -一个类可以*继承(inherit)*另一个类的方法(methods),属性(property)和其它特性。当一个类继承其它类时,继承类叫*子类(subclass)*,被继承类叫*超类(或父类,superclass)*。在 Swift 中,继承是区分「类」与其它类型的一个基本特征。 +一个类可以*继承(inherit)*另一个类的方法(methods),属性(properties)和其它特性。当一个类继承其它类时,继承类叫*子类(subclass)*,被继承类叫*超类(或父类,superclass)*。在 Swift 中,继承是区分「类」与其它类型的一个基本特征。 在 Swift 中,类可以调用和访问超类的方法,属性和下标脚本(subscripts),并且可以重写(override)这些方法,属性和下标脚本来优化或修改它们的行为。Swift 会检查你的重写定义在超类中是否有匹配的定义,以此确保你的重写行为是正确的。 -可以为类中继承来的属性添加属性观察器(property observer),这样一来,当属性值改变时,类就会被通知到。可以为任何属性添加属性观察器,无论它原本被定义为存储型属性(stored property)还是计算型属性(computed property)。 +可以为类中继承来的属性添加属性观察器(property observers),这样一来,当属性值改变时,类就会被通知到。可以为任何属性添加属性观察器,无论它原本被定义为存储型属性(stored property)还是计算型属性(computed property)。 ## 定义一个基类(Base class) @@ -27,7 +27,7 @@ Swift 中的类并不是从一个通用的基类继承而来。如果你不为 下面的例子定义了一个叫`Vehicle`的基类。这个基类声明了一个名为`currentSpeed `,默认值是0.0的存储属性(属性类型推断为`Double `)。`currentSpeed `属性的值被一个`String` 类型的只读计算型属性`description`使用,用来创建车辆的描述。 -`Vehicle`基类也定义了一个名为`makeNoise`的方法。这个方法实际上不为`Vehicle`实例做任何事,但之后将会被`Vehicle`的子类定制 +`Vehicle`基类也定义了一个名为`makeNoise`的方法。这个方法实际上不为`Vehicle`实例做任何事,但之后将会被`Vehicle`的子类定制: ```swift class Vehicle { @@ -41,7 +41,7 @@ class Vehicle { } ``` -您可以用初始化语法创建一个`Vehicle `的新实例,即 `TypeName`后面跟一个空括号: +您可以用初始化语法创建一个`Vehicle `的新实例,即类名后面跟一个空括号: ```swift let someVehicle = Vehicle() ``` @@ -51,7 +51,9 @@ let someVehicle = Vehicle() ```swift println("Vehicle: \(someVehicle.description)") // Vehicle: traveling at 0.0 miles per hour -``` +``` + +`Vehicle`类定义了一个通用特性的车辆类,实际上没什么用处。为了让它变得更加有用,需要改进它能够描述一个更加具体的车辆类。 ## 子类生成(Subclassing) @@ -66,17 +68,13 @@ class SomeClass: SomeSuperclass { } ``` -下一个例子,定义一个更具体的车辆类叫`Bicycle`。这个新类是在 `Vehicle`类的基础上创建起来。因此你需要将`Vehicle`类放在 `Bicycle`类后面,用冒号分隔。 - -我们可以将这读作: - -“定义一个新的类叫`Bicycle `,它继承了`Vehicle`的特性”; - +下一个例子,定义一个叫`Bicycle`的子类,继承成父类`Vehicle` + ```swift class Bicycle: Vehicle { var hasBasket = false } -``` +``` 新的`Bicycle`类自动获得`Vehicle`类的所有特性,比如 `currentSpeed `和`description`属性,还有它的`makeNoise`方法。 @@ -161,7 +159,7 @@ train.makeNoise() ### 重写属性 -你可以重写继承来的实例属性或类属性,提供自己定制的getter和setter,或添加属性观察器使重写的属性观察属性值什么时候发生改变。 +你可以重写继承来的实例属性或类属性,提供自己定制的getter和setter,或添加属性观察器使重写的属性可以观察属性值什么时候发生改变。 #### 重写属性的Getters和Setters @@ -228,7 +226,7 @@ println("AutomaticCar: \(automatic.description)") 你可以通过把方法,属性或下标脚本标记为*`final`*来防止它们被重写,只需要在声明关键字前加上`final`特性即可。(例如:`final var`, `final func`, `final class func`, 以及 `final subscript`) -如果你重写了`final`方法,属性或下标脚本,在编译时会报错。在扩展中,你添加到类里的方法,属性或下标脚本也可以在扩展的定义里标记为 final。 +如果你重写了`final`方法,属性或下标脚本,在编译时会报错。在类扩展中的方法,属性或下标脚本也可以在扩展的定义里标记为 final。 -你可以通过在关键字`class`前添加`final`特性(`final class`)来将整个类标记为 final 的,这样的类是不可被继承的,否则会报编译错误。 +你可以通过在关键字`class`前添加`final`特性(`final class`)来将整个类标记为 final 的,这样的类是不可被继承的,任何子类试图继承此类时,在编译时会报错。