Date: Tue, 30 Jun 2015 18:12:21 +0800
Subject: [PATCH 039/228] 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 040/228] 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 041/228] =?UTF-8?q?=E6=96=B0=E6=B7=BB=E5=8A=A0=E4=BA=86Ext?=
=?UTF-8?q?ending=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一个值的过程:

+
+## 扩展一个泛型类型
+
+当你扩展一个泛型类型的时候,你并不需要在扩展的定义中提供类型参数列表。更加方便的是,原始类型定义中声明的类型参数列表在扩展里是可以使用的,并且这些来自原始类型中的参数名称会被用作原始定义中类型参数的引用。
+
+下面的例子扩展了泛型`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 042/228] =?UTF-8?q?=E5=AE=8C=E6=88=90Generic-Type=20Constr?=
=?UTF-8?q?aint=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 043/228] =?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 044/228] 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 045/228] 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`的值,从而实现移动正方形到新的位置。
@@ -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 046/228] 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 047/228] 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)
-上面所描述的声道模型使用`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 048/228] 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 049/228] 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 3aa84c3a90a3ce4c1129709bbd1805c909de86ec Mon Sep 17 00:00:00 2001
From: Channe
Date: Wed, 1 Jul 2015 19:30:38 +0800
Subject: [PATCH 050/228] =?UTF-8?q?ARC=E4=B8=AD=E8=8B=B1=E6=96=87=E9=80=90?=
=?UTF-8?q?=E5=AD=97=E6=AF=94=E5=AF=B9=E7=BF=BB=E8=AF=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
2.0英文版与原翻译版逐字比对,修改、润色部分翻译
---
.../16_Automatic_Reference_Counting.md | 113 +++++++++---------
1 file changed, 59 insertions(+), 54 deletions(-)
diff --git a/source/chapter2/16_Automatic_Reference_Counting.md b/source/chapter2/16_Automatic_Reference_Counting.md
index 42175064..b0efa8b9 100755
--- a/source/chapter2/16_Automatic_Reference_Counting.md
+++ b/source/chapter2/16_Automatic_Reference_Counting.md
@@ -13,7 +13,7 @@
- [闭包引起的循环强引用](#strong_reference_cycles_for_closures)
- [解决闭包引起的循环强引用](#resolving_strong_reference_cycles_for_closures)
-Swift 使用自动引用计数(ARC)这一机制来跟踪和管理你的应用程序的内存。通常情况下,Swift 的内存管理机制会一直起着作用,你无须自己来考虑内存的管理。ARC 会在类的实例不再被使用时,自动释放其占用的内存。
+Swift 使用自动引用计数(ARC)机制来跟踪和管理你的应用程序的内存。通常情况下,Swift 的内存管理机制会一直起着作用,你无须自己来考虑内存的管理。ARC 会在类的实例不再被使用时,自动释放其占用的内存。
然而,在少数情况下,ARC 为了能帮助你管理内存,需要更多的关于你的代码之间关系的信息。本章描述了这些情况,并且为你示范怎样启用 ARC 来管理你的应用程序的内存。
@@ -23,13 +23,15 @@ Swift 使用自动引用计数(ARC)这一机制来跟踪和管理你的应
## 自动引用计数的工作机制
-当你每次创建一个类的新的实例的时候,ARC 会分配一大块内存用来储存实例的信息。内存中会包含实例的类型信息,以及这个实例所有相关属性的值。此外,当实例不再被使用时,ARC 释放实例所占用的内存,并让释放的内存能挪作他用。这确保了不再被使用的实例,不会一直占用内存空间。
+当你每次创建一个类的新的实例的时候,ARC 会分配一大块内存用来储存实例的信息。内存中会包含实例的类型信息,以及这个实例所有相关属性的值。
+
+此外,当实例不再被使用时,ARC 释放实例所占用的内存,并让释放的内存能挪作他用。这确保了不再被使用的实例,不会一直占用内存空间。
然而,当 ARC 收回和释放了正在被使用中的实例,该实例的属性和方法将不能再被访问和调用。实际上,如果你试图访问这个实例,你的应用程序很可能会崩溃。
-为了确保使用中的实例不会被销毁,ARC 会跟踪和计算每一个实例正在被多少属性,常量和变量所引用。哪怕实例的引用数为一,ARC都不会销毁这个实例。
+为了确保使用中的实例不会被销毁,ARC 会跟踪和计算每一个实例正在被多少属性,常量和变量所引用。哪怕实例的引用数为1,ARC都不会销毁这个实例。
-为了使之成为可能,无论你将实例赋值给属性,常量或者是变量,属性,常量或者变量,都会对此实例创建强引用。之所以称之为强引用,是因为它会将实例牢牢的保持住,只要强引用还在,实例是不允许被销毁的。
+为了使上述成为可能,无论你将实例赋值给属性、常量或变量,它们都会创建此实例的强引用。之所以称之为“强”引用,是因为它会将实例牢牢的保持住,只要强引用还在,实例是不允许被销毁的。
## 自动引用计数实践
@@ -49,9 +51,9 @@ class Person {
}
```
-`Person`类有一个构造函数,此构造函数为实例的`name`属性赋值并打印出信息,以表明初始化过程生效。`Person`类同时也拥有析构函数,同样会在实例被销毁的时候打印出信息。
+`Person`类有一个构造函数,此构造函数为实例的`name`属性赋值,并打印一条消息以表明初始化过程生效。`Person`类也拥有一个析构函数,这个析构函数会在实例被销毁时打印一条消息。
-接下来的代码片段定义了三个类型为`Person?`的变量,用来按照代码片段中的顺序,为新的`Person`实例建立多个引用。由于这些变量是被定义为可选类型(Person?,而不是Person),它们的值会被自动初始化为`nil`,目前还不会引用到`Person`类的实例。
+接下来的代码片段定义了三个类型为`Person?`的变量,用来按照代码片段中的顺序,为新的`Person`实例建立多个引用。由于这些变量是被定义为可选类型(`Person?`,而不是`Person`),它们的值会被自动初始化为`nil`,目前还不会引用到`Person`类的实例。
```swift
var reference1: Person?
@@ -59,7 +61,7 @@ var reference2: Person?
var reference3: Person?
```
-现在你可以创建`Person`类的新实例,并且将它赋值给三个变量其中的一个:
+现在你可以创建`Person`类的新实例,并且将它赋值给三个变量中的一个:
```swift
reference1 = Person(name: "John Appleseed")
@@ -68,25 +70,25 @@ reference1 = Person(name: "John Appleseed")
应当注意到当你调用`Person`类的构造函数的时候,"John Appleseed is being initialized”会被打印出来。由此可以确定构造函数被执行。
-由于`Person`类的新实例被赋值给了`reference1`变量,所以`reference1`到`Person`类的新实例之间建立了一个强引用。正是因为这个强引用,ARC 会保证`Person`实例被保持在内存中不被销毁。
+由于`Person`类的新实例被赋值给了`reference1`变量,所以`reference1`到`Person`类的新实例之间建立了一个强引用。正是因为这一个强引用,ARC 会保证`Person`实例被保持在内存中不被销毁。
-如果你将同样的`Person`实例也赋值给其他两个变量,该实例又会多出两个强引用:
+如果你将同一个`Person`实例也赋值给其他两个变量,该实例又会多出两个强引用:
```swift
reference2 = reference1
reference3 = reference1
```
-现在这个`Person`实例已经有三个强引用了。
+现在这一个`Person`实例已经有三个强引用了。
-如果你通过给两个变量赋值`nil`的方式断开两个强引用()包括最先的那个强引用),只留下一个强引用,`Person`实例不会被销毁:
+如果你通过给其中两个变量赋值`nil`的方式断开两个强引用(包括最先的那个强引用),只留下一个强引用,`Person`实例不会被销毁:
```swift
reference1 = nil
reference2 = nil
-```
-
-ARC 会在第三个,也即最后一个强引用被断开的时候,销毁`Person`实例,这也意味着你不再使用这个`Person`实例:
+```
+
+在你清楚地表明不再使用这个`Person`实例时,即第三个也就是最后一个强引用被断开时,ARC 会销毁它。
```swift
reference3 = nil
@@ -98,9 +100,9 @@ reference3 = nil
在上面的例子中,ARC 会跟踪你所新创建的`Person`实例的引用数量,并且会在`Person`实例不再被需要时销毁它。
-然而,我们可能会写出这样的代码,一个类永远不会有0个强引用。这种情况发生在两个类实例互相保持对方的强引用,并让对方不被销毁。这就是所谓的循环强引用。
+然而,我们可能会写出一个类实例的强引用数永远不能变成0的代码。如果两个类实例互相持有对方的强引用,因而每个实例都让对方一直存在,就是这种情况。这就是所谓的循环强引用。
-你可以通过定义类之间的关系为弱引用或者无主引用,以此替代强引用,从而解决循环强引用的问题。具体的过程在[解决类实例之间的循环强引用](#resolving_strong_reference_cycles_between_class_instances)中有描述。不管怎样,在你学习怎样解决循环强引用之前,很有必要了解一下它是怎样产生的。
+你可以通过定义类之间的关系为弱引用或无主引用,以替代强引用,从而解决循环强引用的问题。具体的过程在[解决类实例之间的循环强引用](#resolving_strong_reference_cycles_between_class_instances)中有描述。不管怎样,在你学习怎样解决循环强引用之前,很有必要了解一下它是怎样产生的。
下面展示了一个不经意产生循环强引用的例子。例子定义了两个类:`Person`和`Apartment`,用来建模公寓和它其中的居民:
@@ -128,14 +130,14 @@ class Apartment {
这两个类都定义了析构函数,用以在类实例被析构的时候输出信息。这让你能够知晓`Person`和`Apartment`的实例是否像预期的那样被销毁。
-接下来的代码片段定义了两个可选类型的变量`john`和`number73`,并分别被设定为下面的`Apartment`和`Person`的实例。这两个变量都被初始化为`nil`,并为可选的:
+接下来的代码片段定义了两个可选类型的变量`john`和`number73`,并分别被设定为下面的`Apartment`和`Person`的实例。这两个变量都被初始化为`nil`,这正是可选的优点:
```swift
var john: Person?
var number73: Apartment?
```
-现在你可以创建特定的`Person`和`Apartment`实例并将类实例赋值给`john`和`number73`变量:
+现在你可以创建特定的`Person`和`Apartment`实例并将赋值给`john`和`number73`变量:
```swift
john = Person(name: "John Appleseed")
@@ -156,15 +158,15 @@ number73!.tenant = john
在将两个实例联系在一起之后,强引用的关系如图所示:

-
-不幸的是,将这两个实例关联在一起之后,一个循环强引用被创建了。`Person`实例现在有了一个指向`Apartment`实例的强引用,而`Apartment`实例也有了一个指向`Person`实例的强引用。因此,当你断开`john`和`number73`变量所持有的强引用时,引用计数并不会降为 0,实例也不会被 ARC 销毁:
+
+不幸的是,这两个实例关联后会产生一个循环强引用。`Person`实例现在有了一个指向`Apartment`实例的强引用,而`Apartment`实例也有了一个指向`Person`实例的强引用。因此,当你断开`john`和`number73`变量所持有的强引用时,引用计数并不会降为 0,实例也不会被 ARC 销毁:
```swift
john = nil
number73 = nil
```
-注意,当你把这两个变量设为`nil`时,没有任何一个析构函数被调用。强引用循环阻止了`Person`和`Apartment`类实例的销毁,并在你的应用程序中造成了内存泄漏。
+注意,当你把这两个变量设为`nil`时,没有任何一个析构函数被调用。循环强引用会一直阻止`Person`和`Apartment`类实例的销毁,这就在你的应用程序中造成了内存泄漏。
在你将`john`和`number73`赋值为`nil`后,强引用关系如下图:
@@ -179,20 +181,20 @@ Swift 提供了两种办法用来解决你在使用类的属性时所遇到的
弱引用和无主引用允许循环引用中的一个实例引用另外一个实例而不保持强引用。这样实例能够互相引用而不产生循环强引用。
-对于生命周期中会变为`nil`的实例使用弱引用。相反的,对于初始化赋值后再也不会被赋值为`nil`的实例,使用无主引用。
+对于生命周期中会变为`nil`的实例使用弱引用。相反地,对于初始化赋值后再也不会被赋值为`nil`的实例,使用无主引用。
### 弱引用
+
+弱引用不会对其引用的实例保持强引用,因而不会阻止 ARC 销毁被引用的实例。这个特性阻止了引用变为循环强引用。声明属性或者变量时,在前面加上`weak`关键字表明这是一个弱引用。
-弱引用不会牢牢保持住引用的实例,并且不会阻止 ARC 销毁被引用的实例。这种行为阻止了引用变为循环强引用。声明属性或者变量时,在前面加上`weak`关键字表明这是一个弱引用。
-
-在实例的生命周期中,如果某些时候引用没有值,那么弱引用可以阻止循环强引用。如果引用总是有值,则可以使用无主引用,在[无主引用](#2)中有描述。在上面`Apartment`的例子中,一个公寓的生命周期中,有时是没有“居民”的,因此适合使用弱引用来解决循环强引用。
+在实例的生命周期中,如果某些时候引用没有值,那么弱引用可以避免循环强引用。如果引用总是有值,则可以使用无主引用,在[无主引用](#2)中有描述。在上面`Apartment`的例子中,一个公寓的生命周期中,有时是没有“居民”的,因此适合使用弱引用来解决循环强引用。
> 注意:
> 弱引用必须被声明为变量,表明其值能在运行时被修改。弱引用不能被声明为常量。
-因为弱引用可以没有值,你必须将每一个弱引用声明为可选类型。可选类型是在 Swift 语言中推荐的用来表示可能没有值的类型。
+因为弱引用可以没有值,你必须将每一个弱引用声明为可选类型。在 Swift 中,推荐使用可选类型描述可能没有值的类型。
-因为弱引用不会保持所引用的实例,即使引用存在,实例也有可能被销毁。因此,ARC 会在引用的实例被销毁后自动将其赋值为`nil`。你可以像其他可选值一样,检查弱引用的值是否存在,你永远也不会遇到被销毁了而不存在的实例。
+因为弱引用不会保持所引用的实例,即使引用存在,实例也有可能被销毁。因此,ARC 会在引用的实例被销毁后自动将其赋值为`nil`。你可以像其他可选值一样,检查弱引用的值是否存在,你将永远不会访问已销毁的实例的引用。
下面的例子跟上面`Person`和`Apartment`的例子一致,但是有一个重要的区别。这一次,`Apartment`的`tenant`属性被声明为弱引用:
@@ -214,7 +216,7 @@ class Apartment {
}
```
-然后跟之前一样,建立两个变量(john和number73)之间的强引用,并关联两个实例:
+然后跟之前一样,建立两个变量(`john`和`number73`)之间的强引用,并关联两个实例:
```swift
var john: Person?
@@ -264,11 +266,11 @@ number73 = nil
> 注意:
>如果你试图在实例被销毁后,访问该实例的无主引用,会触发运行时错误。使用无主引用,你必须确保引用始终指向一个未销毁的实例。
-> 还需要注意的是如果你试图访问实例已经被销毁的无主引用,程序会直接崩溃,而不会发生无法预期的行为。所以你应当避免这样的事情发生。
+> 还需要注意的是如果你试图访问实例已经被销毁的无主引用,Swift 确保程序会直接崩溃,而不会发生无法预期的行为。所以你应当避免这样的事情发生。
-下面的例子定义了两个类,`Customer`和`CreditCard`,模拟了银行客户和客户的信用卡。这两个类中,每一个都将另外一个类的实例作为自身的属性。这种关系会潜在的创造循环强引用。
+下面的例子定义了两个类,`Customer`和`CreditCard`,模拟了银行客户和客户的信用卡。这两个类中,每一个都将另外一个类的实例作为自身的属性。这种关系可能会造成循环强引用。
-`Customer`和`CreditCard`之间的关系与前面弱引用例子中`Apartment`和`Person`的关系截然不同。在这个数据模型中,一个客户可能有或者没有信用卡,但是一张信用卡总是关联着一个客户。为了表示这种关系,`Customer`类有一个可选类型的`card`属性,但是`CreditCard`类有一个非可选类型的`customer`属性。
+`Customer`和`CreditCard`之间的关系与前面弱引用例子中`Apartment`和`Person`的关系略微不同。在这个数据模型中,一个客户可能有或者没有信用卡,但是一张信用卡总是关联着一个客户。为了表示这种关系,`Customer`类有一个可选类型的`card`属性,但是`CreditCard`类有一个非可选类型的`customer`属性。
此外,只能通过将一个`number`值和`customer`实例传递给`CreditCard`构造函数的方式来创建`CreditCard`实例。这样可以确保当创建`CreditCard`实例时总是有一个`customer`实例与之关联。
@@ -287,15 +289,18 @@ class Customer {
```swift
class CreditCard {
- let number: Int
+ let number: UInt64
unowned let customer: Customer
- init(number: Int, customer: Customer) {
+ init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit { print("Card #\(number) is being deinitialized") }
}
-```
+```
+
+> 注意:
+> `CreditCard`类的`number`属性被定义为`UInt64`类型而不是`Int`类型,以确保`number`属性的存储量在32位和64位系统上都能足够容纳16位的卡号。
下面的代码片段定义了一个叫`john`的可选类型`Customer`变量,用来保存某个特定客户的引用。由于是可选类型,所以变量被初始化为`nil`。
@@ -336,13 +341,13 @@ john = nil
`Person`和`Apartment`的例子展示了两个属性的值都允许为`nil`,并会潜在的产生循环强引用。这种场景最适合用弱引用来解决。
-`Customer`和`CreditCard`的例子展示了一个属性的值允许为`nil`,而另一个属性的值不允许为`nil`,并会潜在的产生循环强引用。这种场景最适合通过无主引用来解决。
+`Customer`和`CreditCard`的例子展示了一个属性的值允许为`nil`,而另一个属性的值不允许为`nil`,这也可能会产生循环强引用。这种场景最适合通过无主引用来解决。
-然而,存在着第三种场景,在这种场景中,两个属性都必须有值,并且初始化完成后不能为`nil`。在这种场景中,需要一个类使用无主属性,而另外一个类使用隐式解析可选属性。
+然而,存在着第三种场景,在这种场景中,两个属性都必须有值,并且初始化完成后永远不会为`nil`。在这种场景中,需要一个类使用无主属性,而另外一个类使用隐式解析可选属性。
这使两个属性在初始化完成后能被直接访问(不需要可选展开),同时避免了循环引用。这一节将为你展示如何建立这种关系。
-下面的例子定义了两个类,`Country`和`City`,每个类将另外一个类的实例保存为属性。在这个模型中,每个国家必须有首都,而每一个城市必须属于一个国家。为了实现这种关系,`Country`类拥有一个`capitalCity`属性,而`City`类有一个`country`属性:
+下面的例子定义了两个类,`Country`和`City`,每个类将另外一个类的实例保存为属性。在这个模型中,每个国家必须有首都,每个城市必须属于一个国家。为了实现这种关系,`Country`类拥有一个`capitalCity`属性,而`City`类有一个`country`属性:
```swift
class Country {
@@ -370,7 +375,7 @@ class City {
`Country`的构造函数调用了`City`的构造函数。然而,只有`Country`的实例完全初始化完后,`Country`的构造函数才能把`self`传给`City`的构造函数。([在两段式构造过程中有具体描述](14_Initialization.html))
-为了满足这种需求,通过在类型结尾处加上感叹号(City!)的方式,将`Country`的`capitalCity`属性声明为隐式解析可选类型的属性。这表示像其他可选类型一样,`capitalCity`属性的默认值为`nil`,但是不需要展开它的值就能访问它。([在隐式解析可选类型中有描述](01_The_Basics.html))
+为了满足这种需求,通过在类型结尾处加上感叹号(`City!`)的方式,将`Country`的`capitalCity`属性声明为隐式解析可选类型的属性。这表示像其他可选类型一样,`capitalCity`属性的默认值为`nil`,但是不需要展开它的值就能访问它。([在隐式解析可选类型中有描述](01_The_Basics.html))
由于`capitalCity`默认值为`nil`,一旦`Country`的实例在构造函数中给`name`属性赋值后,整个初始化过程就完成了。这代表一旦`name`属性被赋值后,`Country`的构造函数就能引用并传递隐式的`self`。`Country`的构造函数在赋值`capitalCity`时,就能将`self`作为参数传递给`City`的构造函数。
@@ -387,13 +392,13 @@ print("\(country.name)'s capital city is called \(country.capitalCity.name)")
##闭包引起的循环强引用
-前面我们看到了循环强引用环是在两个类实例属性互相保持对方的强引用时产生的,还知道了如何用弱引用和无主引用来打破循环强引用。
+前面我们看到了循环强引用是在两个类实例属性互相保持对方的强引用时产生的,还知道了如何用弱引用和无主引用来打破这些循环强引用。
-循环强引用还会发生在当你将一个闭包赋值给类实例的某个属性,并且这个闭包体中又使用了实例。这个闭包体中可能访问了实例的某个属性,例如`self.someProperty`,或者闭包中调用了实例的某个方法,例如`self.someMethod`。这两种情况都导致了闭包 “捕获" `self`,从而产生了循环强引用。
+循环强引用还会发生在当你将一个闭包赋值给类实例的某个属性,并且这个闭包体中又使用了这个类实例。这个闭包体中可能访问了实例的某个属性,例如`self.someProperty`,或者闭包中调用了实例的某个方法,例如`self.someMethod`。这两种情况都导致了闭包 “捕获" `self`,从而产生了循环强引用。
循环强引用的产生,是因为闭包和类相似,都是引用类型。当你把一个闭包赋值给某个属性时,你也把一个引用赋值给了这个闭包。实质上,这跟之前的问题是一样的-两个强引用让彼此一直有效。但是,和两个类实例不同,这次一个是类实例,另一个是闭包。
-Swift 提供了一种优雅的方法来解决这个问题,称之为闭包占用列表(closuer capture list)。同样的,在学习如何用闭包占用列表破坏循环强引用之前,先来了解一下循环强引用是如何产生的,这对我们是很有帮助的。
+Swift 提供了一种优雅的方法来解决这个问题,称之为闭包捕获列表(closuer capture list)。同样的,在学习如何用闭包捕获列表破坏循环强引用之前,先来了解一下这里的循环强引用是如何产生的,这对我们很有帮助。
下面的例子为你展示了当一个闭包引用了`self`后是如何产生一个循环强引用的。例子中定义了一个叫`HTMLElement`的类,用一种简单的模型表示 HTML 中的一个单独的元素:
@@ -425,9 +430,9 @@ class HTMLElement {
`HTMLElement`类定义了一个`name`属性来表示这个元素的名称,例如代表段落的"p",或者代表换行的"br"。`HTMLElement`还定义了一个可选属性`text`,用来设置和展现 HTML 元素的文本。
-除了上面的两个属性,`HTMLElement`还定义了一个`lazy`属性`asHTML`。这个属性引用了一个闭包,将`name`和`text`组合成 HTML 字符串片段。该属性是`() -> String`类型,或者可以理解为“一个没有参数,返回`String`的函数”。
+除了上面的两个属性,`HTMLElement`还定义了一个`lazy`属性`asHTML`。这个属性引用了一个将`name`和`text`组合成 HTML 字符串片段的闭包。该属性是`Void -> String`类型,或者可以理解为“一个没有参数,返回`String`的函数”。
-默认情况下,闭包赋值给了`asHTML`属性,这个闭包返回一个代表 HTML 标签的字符串。如果`text`值存在,该标签就包含可选值`text`;如果`text`不存在,该标签就不包含文本。对于段落元素,根据`text`是"some text"还是`nil`,闭包会返回"`some text
`"或者"``"。
+默认情况下,闭包赋值给了`asHTML`属性,这个闭包返回一个代表 HTML 标签的字符串。如果`text`值存在,该标签就包含可选值`text`;如果`text`不存在,该标签就不包含文本。对于段落元素,根据`text`是`"some text"`还是`nil`,闭包会返回"`some text
`"或者"``"。
可以像实例方法那样去命名、使用`asHTML`属性。然而,由于`asHTML`是闭包而不是实例方法,如果你想改变特定元素的 HTML 处理的话,可以用自定义的闭包来取代默认值。
@@ -470,38 +475,38 @@ paragraph = nil
在定义闭包时同时定义捕获列表作为闭包的一部分,通过这种方式可以解决闭包和类实例之间的循环强引用。捕获列表定义了闭包体内捕获一个或者多个引用类型的规则。跟解决两个类实例间的循环强引用一样,声明每个捕获的引用为弱引用或无主引用,而不是强引用。应当根据代码关系来决定使用弱引用还是无主引用。
>注意:
-Swift 有如下要求:只要在闭包内使用`self`的成员,就要用`self.someProperty`或者`self.someMethod`(而不只是`someProperty`或`someMethod`)。这提醒你可能会不小心就捕获了`self`。
+Swift 有如下要求:只要在闭包内使用`self`的成员,就要用`self.someProperty`或者`self.someMethod`(而不只是`someProperty`或`someMethod`)。这提醒你可能会一不小心就捕获了`self`。
-###定义捕获列表
+###定义捕获列表
-捕获列表中的每个元素都是由`weak`或者`unowned`关键字和实例的引用(如`self`或`someInstance`)成对组成。每一对都在方括号中,通过逗号分开。
+捕获列表中的每一项都由一对元素组成,一个元素是`weak`或`unowned`关键字,另一个元素是类实例的引用(如`self`)或初始化过的变量(如`delegate = self.delegate!`)。这些项在方括号中用逗号分开。
-捕获列表放置在闭包参数列表和返回类型之前:
+如果闭包有参数列表和返回类型,把捕获列表放在它们前面:
```swift
lazy var someClosure: (Int, String) -> String = {
- [unowned self] (index: Int, stringToProcess: String) -> String in
+ [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
// closure body goes here
}
```
-如果闭包没有指定参数列表或者返回类型,则可以通过上下文推断,那么可以捕获列表放在闭包开始的地方,跟着是关键字`in`:
+如果闭包没有指明参数列表或者返回类型,即它们会通过上下文推断,那么可以把捕获列表和关键字`in`放在闭包最开始的地方:
```swift
lazy var someClosure: Void -> String = {
- [unowned self] in
+ [unowned self, weak delegate = self.delegate!] in
// closure body goes here
}
```
###弱引用和无主引用
-当闭包和捕获的实例总是互相引用时并且总是同时销毁时,将闭包内的捕获定义为无主引用。
+在闭包和捕获的实例总是互相引用时并且总是同时销毁时,将闭包内的捕获定义为无主引用。
-相反的,当捕获引用有时可能会是`nil`时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为`nil`。这使我们可以在闭包内检查它们是否存在。
+相反的,在被捕获的引用可能会变为`nil`时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为`nil`。这使我们可以在闭包体内检查它们是否存在。
>注意:
-如果捕获的引用绝对不会置为`nil`,应该用无主引用,而不是弱引用。
+如果被捕获的引用绝对不会变为`nil`,应该用无主引用,而不是弱引用。
前面的`HTMLElement`例子中,无主引用是正确的解决循环强引用的方法。这样编写`HTMLElement`类来避免循环强引用:
@@ -532,7 +537,7 @@ class HTMLElement {
}
```
-上面的`HTMLElement`实现和之前的实现一致,只是在`asHTML`闭包中多了一个捕获列表。这里,捕获列表是`[unowned self]`,表示“用无主引用而不是强引用来捕获`self`”。
+上面的`HTMLElement`实现和之前的实现一致,除了在`asHTML`闭包中多了一个捕获列表。这里,捕获列表是`[unowned self]`,表示“用无主引用而不是强引用来捕获`self`”。
和之前一样,我们可以创建并打印`HTMLElement`实例:
From aee32488e24d7688817ef3bc538b0167a9ce469f Mon Sep 17 00:00:00 2001
From: chenYuheng
Date: Wed, 1 Jul 2015 21:44:44 +0800
Subject: [PATCH 051/228] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E5=A4=84pri?=
=?UTF-8?q?ntln=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 052/228] =?UTF-8?q?swift=202.0,=2013=5FInheritance,?=
=?UTF-8?q?=E7=BB=A7=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 的,这样的类是不可被继承的,任何子类试图继承此类时,在编译时会报错。
From d324bae47d7151ff9a5fe37119a7b502e0685f1c Mon Sep 17 00:00:00 2001
From: justaway
Date: Fri, 3 Jul 2015 00:35:54 +0800
Subject: [PATCH 053/228] =?UTF-8?q?'25=5FAdvanced=5FOperators'=E4=B8=AD?=
=?UTF-8?q?=E7=9A=84=E6=8C=89=E4=BD=8D=E5=8F=96=E5=8F=8D=E5=B0=8F=E8=8A=82?=
=?UTF-8?q?=E7=BF=BB=E8=AF=91=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/25_Advanced_Operators.md | 26 ++++++++++++------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/source/chapter2/25_Advanced_Operators.md b/source/chapter2/25_Advanced_Operators.md
index 9e1e26a7..1badc3b8 100644
--- a/source/chapter2/25_Advanced_Operators.md
+++ b/source/chapter2/25_Advanced_Operators.md
@@ -12,37 +12,37 @@
- [运算符函数(Operator Functions)](#operator_functions)
- [自定义运算符](#custom_operators)
-除了[基本操作符](02_Basic_Operators.html)中所讲的运算符,Swift还有许多复杂的高级运算符,包括了C语言和Objective-C中的位运算符和移位运算。
+除了在之前介绍过的[基本运算符](02_Basic_Operators.html),Swift 中还有许多可以对数值进行复杂操作的高级运算符。这些高级运算符包含了在 C 和 Objective-C 中已经被大家所熟知的位运算符和移位运算符。
-不同于C语言中的数值计算,Swift的数值计算默认是不可溢出的。溢出行为会被捕获并报告为错误。你是故意的?好吧,你可以使用Swift为你准备的另一套默认允许溢出的数值运算符,如可溢出的加号为`&+`。所有允许溢出的运算符都是以`&`开始的。
+与C语言中的算术运算符不同,Swift 中的算术运算符默认是不会溢出的。所有溢出行为都会被捕获并报告为错误。如果想让系统允许溢出行为,可以选择使用 Swift 中另一套默认支持溢出的运算符,比如溢出加法运算符(`&+`)。所有的这些溢出运算符都是以 `&` 开头的。
-自定义的结构,类和枚举,是否可以使用标准的运算符来定义操作?当然可以!在Swift中,你可以为你创建的所有类型定制运算符的操作。
+在定义自有的结构体、类和枚举时,最好也同时为它们提供标准swift运算符的实现。Swift简化了运算符的自定义实现,也使判断不同类型所对应的行为更为简单。
-可定制的运算符并不限于那些预设的运算符,你可以自定义中置,前置,后置及赋值运算符,当然还有优先级和结合性。这些运算符在代码中可以像预设的运算符一样使用,你也可以扩展已有的类型以支持你自定义的运算符。
+我们不用被预定义的运算符所限制。在 Swift 当中可以自由地定义中缀、前缀、后缀和赋值运算符,以及相应的优先级与结合性。这些运算符在代码中可以像预设的运算符一样使用,我们甚至可以扩展已有的类型以支持自定义的运算符。
## 位运算符
-位操作符可以操作数据结构中原始数据的每个比特位。位操作符通常在诸如图像处理和创建设备驱动等底层开发中使用,位操作符在同外部资源的数据进行交互的时候也很有用,比如在使用用户协议进行通信的时候,运用位运算符来对原始数据进行编码和解码。
+位运算符(`Bitwise operators`)可以操作一个数据结构中每个独立的比特位。它们通常被用在底层开发中,比如图形编程和创建设备驱动。位运算符在处理外部资源的原始数据时也十分有用,比如对自定义通信协议传输的数据进行编码和解码。
-Swift支持如下所有C语言的位运算符:
+Swift 支持C语言中的全部位运算符,具体如下:
-### 按位取反运算符
+### 按位取反运算符(`bitwise NOT operator`)
-按位取反运算符`~`对一个操作数的每一位都取反。
+按位取反运算符(`~`) 可以对一个数值的全部比特位进行取反:
-
+
-这个运算符是前置的,所以请不加任何空格地写在操作数之前。
+按位取反操作符是一个前置运算符,需要直接放在操作数的之前,并且它们之间不能添加任何空格。
-```swift
+```
let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits // 等于 0b11110000
```
-`UInt8`是8位无符整型,可以存储0~255之间的任意数。这个例子初始化一个整型为二进制值`00001111`(前4位为`0`,后4位为`1`),它的十进制值为`15`。
+`UInt8` 类型的整数有 8 个比特位,可以存储 0 ~ 255之间的任意整数。这个例子初始化了一个 `UInt8` 类型的整数,其二进制值为 `00001111`,它的前 4 位都为`0`,后 4 位都为`1`。这个值等价于十进制的 `15` 。
-使用按位取反运算`~`对`initialBits`操作,然后赋值给`invertedBits`这个新常量。这个新常量的值等于所有位都取反的`initialBits`,即`1`变成`0`,`0`变成`1`,变成了`11110000`,十进制值为`240`。
+接着使用按位取反运算符创建了一个名为 `invertedBits` 的常量,这个常量的值与全部比特位取反后的 `initialBits` 相等。即所有的 `0` 都变成了 `1`,同时所有的 `1` 都变成 `0`。`invertedBits` 的二进制值为 `11110000`,等价于无符号十进制数的 `240`。
### 按位与运算符
From c274e371837228e412be7a375806fb1552425bb4 Mon Sep 17 00:00:00 2001
From: justaway
Date: Fri, 3 Jul 2015 12:32:00 +0800
Subject: [PATCH 054/228] =?UTF-8?q?'25=5FAdvanced=5FOperators'=E7=BF=BB?=
=?UTF-8?q?=E8=AF=91=E5=88=B0=E6=BA=A2=E5=87=BA=E8=BF=90=E7=AE=97=E7=AC=A6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/25_Advanced_Operators.md | 94 +++++++++++++-----------
1 file changed, 50 insertions(+), 44 deletions(-)
diff --git a/source/chapter2/25_Advanced_Operators.md b/source/chapter2/25_Advanced_Operators.md
index 1badc3b8..4dd48634 100644
--- a/source/chapter2/25_Advanced_Operators.md
+++ b/source/chapter2/25_Advanced_Operators.md
@@ -23,13 +23,13 @@
## 位运算符
-位运算符(`Bitwise operators`)可以操作一个数据结构中每个独立的比特位。它们通常被用在底层开发中,比如图形编程和创建设备驱动。位运算符在处理外部资源的原始数据时也十分有用,比如对自定义通信协议传输的数据进行编码和解码。
+位运算符(`Bitwise operators`)可以操作一个数据结构中每个独立的位。它们通常被用在底层开发中,比如图形编程和创建设备驱动。位运算符在处理外部资源的原始数据时也十分有用,比如对自定义通信协议传输的数据进行编码和解码。
Swift 支持C语言中的全部位运算符,具体如下:
### 按位取反运算符(`bitwise NOT operator`)
-按位取反运算符(`~`) 可以对一个数值的全部比特位进行取反:
+按位取反运算符(`~`) 可以对一个数值的全部位进行取反:

@@ -40,47 +40,47 @@ let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits // 等于 0b11110000
```
-`UInt8` 类型的整数有 8 个比特位,可以存储 0 ~ 255之间的任意整数。这个例子初始化了一个 `UInt8` 类型的整数,其二进制值为 `00001111`,它的前 4 位都为`0`,后 4 位都为`1`。这个值等价于十进制的 `15` 。
+`UInt8` 类型的整数有 8 个比特位,可以存储 0 ~ 255之间的任意整数。这个例子初始化了一个 `UInt8` 类型的整数,并赋值为二进制的 `00001111`,它的前 4 位都为`0`,后 4 位都为`1`。这个值等价于十进制的 `15` 。
-接着使用按位取反运算符创建了一个名为 `invertedBits` 的常量,这个常量的值与全部比特位取反后的 `initialBits` 相等。即所有的 `0` 都变成了 `1`,同时所有的 `1` 都变成 `0`。`invertedBits` 的二进制值为 `11110000`,等价于无符号十进制数的 `240`。
+接着使用按位取反运算符创建了一个名为 `invertedBits` 的常量,这个常量的值与全部位取反后的 `initialBits` 相等。即所有的 `0` 都变成了 `1`,同时所有的 `1` 都变成 `0`。`invertedBits` 的二进制值为 `11110000`,等价于无符号十进制数的 `240`。
-### 按位与运算符
+### 按位与运算符(Bitwise AND Operator)
-按位与运算符对两个数进行操作,然后返回一个新的数,这个数的每个位都需要两个输入数的同一位都为1时才为1。
+按位与运算符(`&`)可以对两个数的比特位进行合并。它返回一个新的数,只有当两个操作数的对应位*都*为 `1` 的时候,该数的对应位才为 `1`。

-以下代码,`firstSixBits`和`lastSixBits`中间4个位都为1。对它俩进行按位与运算后,就得到了`00111100`,即十进制的`60`。
+在下面的示例当中,`firstSixBits` 和 `lastSixBits` 中间 4 个位的值都为 1 。按位与运算符对它们进行了运算,得到二进制数值 `00111100`,等价于无符号十进制数的 `60`:
-```swift
+```
let firstSixBits: UInt8 = 0b11111100
let lastSixBits: UInt8 = 0b00111111
let middleFourBits = firstSixBits & lastSixBits // 等于 00111100
```
-### 按位或运算
+### 按位或运算符(Bitwise OR Operator)
-按位或运算符`|`比较两个数,然后返回一个新的数,这个数的每一位设置1的条件是两个输入数的同一位都不为0(即任意一个为1,或都为1)。
+按位或运算符(`|`)可以对两个数的比特位进行比较。它返回一个新的数,只要两个操作数的对应位中有*任意*一个为 `1` 时,该数的对应位就为 `1`。

-如下代码,`someBits`和`moreBits`在不同位上有`1`。按位或运行的结果是`11111110`,即十进制的`254`。
+在下面的示例当中,`someBits` 和 `moreBits` 将不同的位设置为 `1`。接位或运算符对它们进行了运算,得到二进制数值 `11111110`,等价于无符号十进制数的 `254`:
-```swift
+```
let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedbits = someBits | moreBits // 等于 11111110
```
-### 按位异或运算符
+### 按位异或运算符(Bitwise XOR Opoerator)
-按位异或运算符`^`比较两个数,然后返回一个数,这个数的每个位设为`1`的条件是两个输入数的同一位不同,如果相同就设为`0`。
+按位异或运算符(`^`)可以对两个数的比特位进行比较。它返回一个新的数,当两个操作数的对应位不相同时,该数的对应位就为 `1`:

-以下代码,`firstBits`和`otherBits`都有一个`1`跟另一个数不同的。所以按位异或的结果是把它这些位置为`1`,其他都置为`0`。
+在下面的示例当中,`firstBits` 和 `otherBits` 都有一个自己设置为 `1` 而对方设置为 `0` 的位。 按位异或运算符将这两个位都设置为 `1`,同时将其它位都设置为 `0`:
-```swift
+```
let firstBits: UInt8 = 0b00010100
let otherBits: UInt8 = 0b00000101
let outputBits = firstBits ^ otherBits // 等于 00010001
@@ -88,21 +88,27 @@ let outputBits = firstBits ^ otherBits // 等于 00010001
### 按位左移/右移运算符
-左移运算符`<<`和右移运算符`>>`会把一个数的所有比特位按以下定义的规则向左或向右移动指定位数。
+按位左移运算符(`<<`)和按位右移运算符(`>>`)可以对一个数进行指定位数的左移和右移,但是需要遵守下面定义的规则。
-按位左移和按位右移的效果相当把一个整数乘于或除于一个因子为`2`的整数。向左移动一个整型的比特位相当于把这个数乘于`2`,向右移一位就是除于`2`。
+对一个数进行按位左移或按位右移,相当于对这个数进行乘以 2 或除以 2 的运算。将一个整数左移一位,等价于将这个数乘以 2,同样地,将一个整数右移一位,等价于将这个数除以 2。
-#### 无符整型的移位操作
+#### 无符号整型的移位操作
-对无符整型的移位的效果如下:
+对无符号整型进行移位的规则如下:
-已经存在的比特位向左或向右移动指定的位数。被移出整型存储边界的的位数直接抛弃,移动留下的空白位用零`0`来填充。这种方法称为逻辑移位。
+1. 已经存在的比特位按指定的位数进行左移和右移。
+2. 任何移动超出整型存储边界的位都会被丢弃。
+3. 用 0 来填充移动后产生的空白位。
-以下这张把展示了 `11111111 << 1`(`11111111`向左移1位),和 `11111111 >> 1`(`11111111`向右移1位)。蓝色的是被移位的,灰色是被抛弃的,橙色的`0`是被填充进来的。
+这种方法称为逻辑移位(`logical shift`)。
+
+以下这张图展示了 `11111111 << 1`(即把 `11111111` 向左移动 1 位),和 `11111111 >> 1`(即把 `11111111` 向右移动 1 位) 的结果。蓝色的部分是被移位的,灰色的部分是被抛弃的,橙色的部分则是被填充进来的。

-```swift
+下面的代码演示了 Swift 中的移位操作:
+
+```
let shiftBits: UInt8 = 4 // 即二进制的00000100
shiftBits << 1 // 00001000
shiftBits << 2 // 00010000
@@ -111,62 +117,62 @@ shiftBits << 6 // 00000000
shiftBits >> 2 // 00000001
```
-你可以使用移位操作进行其他数据类型的编码和解码。
+可以使用移位操作对其他的数据类型进行编码和解码:
-```swift
+```
let pink: UInt32 = 0xCC6699
let redComponent = (pink & 0xFF0000) >> 16 // redComponent 是 0xCC, 即 204
let greenComponent = (pink & 0x00FF00) >> 8 // greenComponent 是 0x66, 即 102
let blueComponent = pink & 0x0000FF // blueComponent 是 0x99, 即 153
```
-这个例子使用了一个`UInt32`的命名为`pink`的常量来存储层叠样式表`CSS`中粉色的颜色值,`CSS`颜色`#CC6699`在Swift用十六进制`0xCC6699`来表示。然后使用按位与(&)和按位右移就可以从这个颜色值中解析出红(CC),绿(66),蓝(99)三个部分。
+这个示例使用了一个命名为 `pink` 的 `UInt32` 型常量来存储层叠样式表(`CSS`)中粉色的颜色值。该 `CSS` 的十六进制颜色值 `#CC6699`, 在 Swift 中表示为 `0xCC6699`。然后利用按位与运算符(`&`)和按位右移运算符(`>>`)从这个颜色值中分解出红(`CC`)、绿(`66`)以及蓝(`99`)三个部分。
-对`0xCC6699`和`0xFF0000`进行按位与`&`操作就可以得到红色部分。`0xFF0000`中的`0`了遮盖了`OxCC6699`的第二和第三个字节,这样`6699`被忽略了,只留下`0xCC0000`。
+红色部分是通过对 `0xCC6699` 和 `0xFF0000` 进行按位与运算后得到的。`0xFF0000` 中的 `0` 部分作为*掩码*,掩盖了 `OxCC6699` 中的第二和第三个字节,使得数值中的 `6699` 被忽略,只留下 `0xCC0000`。
-然后,按向右移动16位,即 `>> 16`。十六进制中每两个字符是8比特位,所以移动16位的结果是把`0xCC0000`变成`0x0000CC`。这和`0xCC`是相等的,就是十进制的`204`。
+然后,再将这个数按向右移动 16 位(`>> 16`)。十六进制中每两个字符表示 8 个比特位,所以移动 16 位后 `0xCC0000` 就变为 `0x0000CC`。这个数和`0xCC`是等同的,也就是十进制数值的 `204`。
-同样的,绿色部分来自于`0xCC6699`和`0x00FF00`的按位操作得到`0x006600`。然后向右移动8位,得到`0x66`,即十进制的`102`。
+同样的,绿色部分通过对 `0xCC6699` 和 `0x00FF00` 进行按位与运算得到 `0x006600`。然后将这个数向右移动 8 位,得到 `0x66`,也就是十进制数值的 `102`。
-最后,蓝色部分对`0xCC6699`和`0x0000FF`进行按位与运算,得到`0x000099`,无需向右移位了,所以结果就是`0x99`,即十进制的`153`。
+最后,蓝色部分通过对 `0xCC6699` 和 `0x0000FF` 进行按位与运算得到 `0x000099`。并且不需要进行向右移位,所以结果为 `0x99` ,也就是十进制数值的 `153`。
-#### 有符整型的移位操作
+#### 有符号整型的移位操作
-有符整型的移位操作相对复杂得多,因为正负号也是用二进制位表示的。(这里举的例子虽然都是8位的,但它的原理是通用的。)
+对比无符号整型来说,有符整型的移位操作相对复杂得多,这种复杂性源于有符号整数的二进制表现形式。(为了简单起见,以下的示例都是基于 8 位有符号整数的,但是其中的原理对任何位数的有符号整数都是通用的。)
-有符整型通过第1个比特位(称为符号位)来表达这个整数是正数还是负数。`0`代表正数,`1`代表负数。
+有符号整数使用第 1 个比特位(通常被称为符号位)来表示这个数的正负。符号位为 `0` 代表正数,为 `1` 代表负数。
-其余的比特位(称为数值位)存储其实值。有符正整数和无符正整数在计算机里的存储结果是一样的,下来我们来看`+4`内部的二进制结构。
+其余的比特位(通常被称为数值位)存储了这个数的真实值。有符号正整数和无符号数的存储方式是一样的,都是从 `0` 开始算起。这是值为 `4` 的 `Int8` 型整数的二进制位表现形式:

-符号位为`0`,代表正数,另外7比特位二进制表示的实际值就刚好是`4`。
+符号位为 `0`,说明这是一个正数,另外 7 位则代表了十进制数值 `4` 的二进制表示。
-负数呢,跟正数不同。负数存储的是2的n次方减去它的绝对值,n为数值位的位数。一个8比特的数有7个数值位,所以是2的7次方,即128。
+负数的存储方式略有不同。它存储的是 `2` 的 n 次方减去它的真实值绝对值,这里的 n 为数值位的位数。一个 8 位的数有 7 个数值位,所以是 2 的 7 次方,即 128。
-我们来看`-4`存储的二进制结构。
+这是值为 `-4` 的 `Int8` 型整数的二进制位表现形式:

-现在符号位为`1`,代表负数,7个数值位要表达的二进制值是124,即128 - 4。
+这次的符号位为 `1`,说明这是一个负数,另外 7 个位则代表了数值 `124`(即 `128 - 4`) 的二进制表示。

-负数的编码方式称为二进制补码表示。这种表示方式看起来很奇怪,但它有几个优点。
+负数的表示通常被称为二进制补码(`two's complement`)表示法。用这种方法来表示负数乍看起来有点奇怪,但它有几个优点。
-首先,只需要对全部8个比特位(包括符号)做标准的二进制加法就可以完成 `-1 + -4` 的操作,忽略加法过程产生的超过8个比特位表达的任何信息。
+首先,如果想对 `-1` 和 `-4` 进行加法操作,我们只需要将这两个数的全部 8 个比特位进行相加,并且将计算结果中超出 8 位的数值丢弃:

-第二,由于使用二进制补码表示,我们可以和正数一样对负数进行按位左移右移的,同样也是左移1位时乘于`2`,右移1位时除于`2`。要达到此目的,对有符整型的右移有一个特别的要求:
+其次,使用二进制补码可以使负数的按位左移和右移操作得到跟正数同样的效果,即每向左移一位就将自身的数值乘以 2,每向右一位就将自身的数值除以 2。要达到此目的,对有符号整数的右移有一个额外的规则:
-对有符整型按位右移时,不使用0填充空白位,而是根据符号位(正数为`0`,负数为`1`)填充空白位。
+* 当对正整数进行按位右移操作时,遵循与无符号整数相同的规则,但是对于移位产生的空白位使用*符号位*进行填充,而不是用 0。

-这就确保了在右移的过程中,有符整型的符号不会发生变化。这称为算术移位。
+这个行为可以确保有符号整数的符号位不会因为右移操作而改变,这通常被称为算术移位(`arithmetic shift`)。
-正因为正数和负数特殊的存储方式,向右移位使它接近于`0`。移位过程中保持符号会不变,负数在接近`0`的过程中一直是负数。
+由于正数和负数的特殊存储方式,在对它们进行右移的时候,会使它们越来越接近 0。在移位的过程中保持符号位不变,意味着负整数在接近 `0` 的过程中会一直保持为负。
## 溢出运算符
From 479e3a39174309a9a990c7c83ab32bfc591a0569 Mon Sep 17 00:00:00 2001
From: justaway
Date: Fri, 3 Jul 2015 16:28:19 +0800
Subject: [PATCH 055/228] =?UTF-8?q?'25=5FAdvanced=5FOperators'=E7=BF=BB?=
=?UTF-8?q?=E8=AF=91=E5=88=B0=E4=BC=98=E5=85=88=E7=BA=A7=E5=92=8C=E7=BB=93?=
=?UTF-8?q?=E5=90=88=E6=80=A7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/25_Advanced_Operators.md | 106 ++++++++++-------------
1 file changed, 45 insertions(+), 61 deletions(-)
diff --git a/source/chapter2/25_Advanced_Operators.md b/source/chapter2/25_Advanced_Operators.md
index 4dd48634..b641866b 100644
--- a/source/chapter2/25_Advanced_Operators.md
+++ b/source/chapter2/25_Advanced_Operators.md
@@ -177,95 +177,79 @@ let blueComponent = pink & 0x0000FF // blueComponent 是 0x99, 即 153
## 溢出运算符
-默认情况下,当你往一个整型常量或变量赋于一个它不能承载的大数时,Swift不会让你这么干的,它会报错。这样,在操作过大或过小的数的时候就很安全了。
+在默认情况下,当向一个整数赋超过它容量的值时,Swift 默认会报错,而不是生成一个无效的数。这个行为给我们操作过大或着过小的数的时候提供了额外的安全性。
-例如,`Int16`整型能承载的整数范围是`-32768`到`32767`,如果给它赋上超过这个范围的数,就会报错:
+例如,`Int16` 型整数能容纳的有符号整数范围是 `-32768` 到 `32767`,当为一个 `Int16` 型变量赋的值超过这个范围时,系统就会报错:
-```swift
+```
var potentialOverflow = Int16.max
-// potentialOverflow 等于 32767, 这是 Int16 能承载的最大整数
+// potentialOverflow 的值是 32767, 这是 Int16 能容纳的最大整数
+
potentialOverflow += 1
-// 噢, 出错了
+// 这里会报错
```
-对过大或过小的数值进行错误处理让你的数值边界条件更灵活。
+为过大或者过小的数值提供错误处理,能让我们在处理边界值时更加灵活。
-当然,你有意在溢出时对有效位进行截断,你可采用溢出运算,而非错误处理。Swfit为整型计算提供了5个`&`符号开头的溢出运算符。
+然而,也可以选择让系统在数值溢出的时候采取截断操作,而非报错。可以使用 Swift 提供的三个溢出操作符(`overflow operators`)来让系统支持整数溢出运算。这些操作符都是以 `&` 开头的:
-- 溢出加法 `&+`
-- 溢出减法 `&-`
-- 溢出乘法 `&*`
-- 溢出除法 `&/`
-- 溢出求余 `&%`
+* 溢出加法 `&+`
+* 溢出减法 `&-`
+* 溢出乘法 `&*`
-### 值的上溢出
+### 数值溢出
-下面例子使用了溢出加法`&+`来解剖的无符整数的上溢出
+数值有可能出现上溢或者下溢。
-```swift
-var willOverflow = UInt8.max
-// willOverflow 等于UInt8的最大整数 255
-willOverflow = willOverflow &+ 1
-// 此时 willOverflow 等于 0
+这个示例演示了当我们对一个无符号整数使用溢出加法(`&+`)进行上溢运算时会发生什么:
+```
+var unsignedOverflow = UInt8.max
+// unsignedOverflow 等于 UInt8 所能容纳的最大整数 255
+
+unsignedOverflow = unsignedOverflow &+ 1
+// 此时 unsignedOverflow 等于 0
```
-`willOverflow`用`Int8`所能承载的最大值`255`(二进制`11111111`),然后用`&+`加1。然后`UInt8`就无法表达这个新值的二进制了,也就导致了这个新值上溢出了,大家可以看下图。溢出后,新值在`UInt8`的承载范围内的那部分是`00000000`,也就是`0`。
+`unsignedOverflow` 被初始化为 `UInt8` 所能容纳的最大整数(`255`,以二进制表示即 `11111111`)。然后使用了溢出加法运算符(`&+`)对其进行加 1 操作。这使得它的二进制表示正好超出 `UInt8` 所能容纳的位数,也就导致了数值的溢出,如下图所示。数值溢出后,留在 `UInt8` 边界内的值是 `00000000`,也就是十进制数值的 0。

-### 值的下溢出
+同样地,当我们对一个无符号整数使用溢出减法(`&-`)进行下溢运算时也会产生类似的现象:
-数值也有可能因为太小而越界。举个例子:
+```
+var unsignedOverflow = UInt8.min
+// unsignedOverflow 等于 UInt8 所能容纳的最小整数 0
-`UInt8`的最小值是`0`(二进制为`00000000`)。使用`&-`进行溢出减1,就会得到二进制的`11111111`即十进制的`255`。
-
-
-
-Swift代码是这样的:
-
-```swift
-var willUnderflow = UInt8.min
-// willUnderflow 等于UInt8的最小值0
-willUnderflow = willUnderflow &- 1
-// 此时 willUnderflow 等于 255
+unsignedOverflow = unsignedOverflow &- 1
+// 此时 unsignedOverflow 等于 255
```
-有符整型也有类似的下溢出,有符整型所有的减法也都是对包括在符号位在内的二进制数进行二进制减法的,这在 "按位左移/右移运算符" 一节提到过。最小的有符整数是`-128`,即二进制的`10000000`。用溢出减法减去去1后,变成了`01111111`,即UInt8所能承载的最大整数`127`。
+`UInt8` 型整数能容纳的最小值是 0,以二进制表示即 `00000000`。当使用溢出减法运算符对其进行减 1 操作时,数值会产生下溢并被截断为 `11111111`, 也就是十进制数值的 255。
+
+
+
+溢出也会发生在有符号整型数值上。在对有符号整型数值进行溢出加法或溢出减法运算时,符号位也需要参与计算,正如[按位左移/右移运算符](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-ID34)所描述的。
+
+```
+var signedOverflow = Int8.min
+// signedOverflow 等于 Int8 所能容纳的最小整数 -128
+
+signedOverflow = signedOverflow &- 1
+// 此时 signedOverflow 等于 127
+```
+
+`Int8` 型整数能容纳的最小值是 -128,以二进制表示即 `10000000`。当使用溢出减法操作符对其进行减 1 操作时,符号位被翻转,得到二进制数值 `01111111`,也就是十进制数值的 `127`,这个值也是 `Int8` 型整数所能容纳的最大值。

-来看看Swift代码:
-
-```swift
-var signedUnderflow = Int8.min
-// signedUnderflow 等于最小的有符整数 -128
-signedUnderflow = signedUnderflow &- 1
-// 此时 signedUnderflow 等于 127
-```
-
-### 除零溢出
-
-一个数除以0 `i / 0`,或者对0求余数 `i % 0`,就会产生一个错误。
-
-```swift
-let x = 1
-let y = x / 0
-```
-
-使用它们对应的可溢出的版本的运算符`&/`和`&%`进行除0操作时就会得到`0`值。
-
-```swift
-let x = 1
-let y = x &/ 0
-// y 等于 0
-```
+对于无符号与有符号整型数值来说,当出现上溢时,它们会从数值所能容纳的最大数变成最小的数。同样地,当发生下溢时,它们会从所能容纳的最小数变成最大的数。
## 优先级和结合性
-运算符的优先级使得一些运算符优先于其他运算符,高优先级的运算符会先被计算。
+运算符的优先级(`precedence`)使得一些运算符优先于其他运算符,高优先级的运算符会先被计算。
-结合性定义相同优先级的运算符在一起时是怎么组合或关联的,是和左边的一组呢,还是和右边的一组。意思就是,到底是和左边的表达式结合呢,还是和右边的表达式结合?
+结合性(`associativity`)定义相同优先级的运算符在一起时是怎么组合或关联的,是和左边的一组呢,还是和右边的一组。意思就是,到底是和左边的表达式结合呢,还是和右边的表达式结合?
在混合表达式中,运算符的优先级和结合性是非常重要的。举个例子,为什么下列表达式的结果为`4`?
From d41d1c550bb1b7954e3154878a4b87203e475ef1 Mon Sep 17 00:00:00 2001
From: littledogboy
Date: Fri, 3 Jul 2015 23:08:18 +0800
Subject: [PATCH 056/228] =?UTF-8?q?statement=E7=BF=BB=E8=AF=91=E5=AE=8C?=
=?UTF-8?q?=E6=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
statement翻译完毕,一代目翻译
---
source/chapter3/10_Statements.md | 217 ++++++++++++++++++++++++++-----
1 file changed, 183 insertions(+), 34 deletions(-)
diff --git a/source/chapter3/10_Statements.md b/source/chapter3/10_Statements.md
index c9bf88f9..7a98a9b1 100755
--- a/source/chapter3/10_Statements.md
+++ b/source/chapter3/10_Statements.md
@@ -1,5 +1,5 @@
-> 翻译:[coverxit](https://github.com/coverxit)
-> 校对:[numbbbbb](https://github.com/numbbbbb), [coverxit](https://github.com/coverxit), [stanzhai](https://github.com/stanzhai)
+> 翻译:[coverxit](https://github.com/coverxit),[littledogboy](https://github.com/littledogboy)
+> 校对:[numbbbbb](https://github.com/numbbbbb), [coverxit](https://github.com/coverxit), [stanzhai](https://github.com/stanzhai),[littledogboy](https://github.com/littledogboy)
# 语句
-----------------
@@ -11,7 +11,7 @@
- [带标签的语句](#labeled_statement)
- [控制传递语句](#control_transfer_statements)
-在 Swift 中,有两种类型的语句:简单语句和控制流语句。简单语句是最常见的,用于构造表达式和声明。控制流语句则用于控制程序执行的流程,Swift 中有三种类型的控制流语句:循环语句、分支语句和控制传递语句。
+在 Swift 中,有两种类型的语句:简单语句和控制流语句。简单语句是最常见的,用于构造表达式或者声明。控制流语句则用于控制程序执行的流程,Swift 中有三种类型的控制流语句:循环语句、分支语句和控制传递语句。
循环语句用于重复执行代码块;分支语句用于执行满足特定条件的代码块;控制传递语句则用于修改代码的执行顺序。在稍后的叙述中,将会详细地介绍每一种类型的控制流语句。
@@ -23,7 +23,8 @@
> *语句* → [*循环语句*](..\chapter3\10_Statements.html#loop_statement) **;** _可选_
> *语句* → [*分支语句*](..\chapter3\10_Statements.html#branch_statement) **;** _可选_
> *语句* → [*标记语句(Labeled Statement)*](..\chapter3\10_Statements.html#labeled_statement)
-> *语句* → [*控制转移语句*](..\chapter3\10_Statements.html#control_transfer_statement) **;** _可选_
+> *语句* → [*控制转移语句*](..\chapter3\10_Statements.html#control_transfer_statement) **;** _可选_
+> *语句* → [*XXX语句*](..\chapter3\10_Statements.html#control_transfer_statement) **;** _可选_
> *多条语句(Statements)* → [*语句*](..\chapter3\10_Statements.html#statement) [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements) _可选_
@@ -41,7 +42,7 @@
### For 语句
-`for`语句允许在重复执行代码块的同时,递增一个计数器。
+`for`语句只有在循环条件为真时重复执行代码块,此时计数器递增。
`for`语句的形式如下:
@@ -53,12 +54,12 @@
`for`语句的执行流程如下:
-1. *initialzation* 只会被执行一次,通常用于声明和初始化在接下来的循环中需要使用的变量。
-2. 计算 *condition* 表达式:
- 如果为`true`,*statements* 将会被执行,然后转到第3步。如果为`false`,*statements* 和 *increment* 都不会被执行,`for`至此执行完毕。
+1. *initialzation* *循环变量* 只会被执行一次,通常用于声明和初始化在接下来的循环中需要使用的变量。
+2. 判断 *condition* 循环条件:
+ 如果为`true`,*statements* *循环体* 将会被执行,然后转到第3步。如果为`false`,*statements* 和 *increment* *循环增量* 都不会被执行,`for`至此执行完毕。
3. 计算 *increment* 表达式,然后转到第2步。
-定义在 *initialzation* 中的变量仅在`for`语句的作用域以内有效。*condition* 表达式的值的类型必须遵循`LogicValue`协议。
+在 *initialzation* 中定义的变量仅在`for`循环的作用域内有效。*condition* 表达式的值的类型必须遵循`BooleanType `协议。
> For 循环语法
> *for语句* → **for** [*for初始条件*](..\chapter3\10_Statements.html#for_init) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block)
@@ -82,7 +83,7 @@
### While 语句
-`while`语句允许重复执行代码块。
+`while`语句当循环条件为真时,允许重复执行代码块。
`while`语句的形式如下:
@@ -98,34 +99,37 @@
由于 *condition* 的值在 *statements* 执行前就已计算出,因此`while`语句中的 *statements* 可能会被执行若干次,也可能不会被执行。
-*condition* 表达式的值的类型必须遵循`LogicValue`协议。同时,*condition* 表达式也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
+*condition* 表达式的值的类型必须遵循`BooleanType `协议。同时,*condition* 表达式也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
> While 循环语法
> *while语句* → **while** [*while条件*](..\chapter3\10_Statements.html#while_condition) [*代码块*](..\chapter3\05_Declarations.html#code_block)
-> *while条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*声明*](..\chapter3\05_Declarations.html#declaration)
+> *while条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*声明*](..\chapter3\05_Declarations.html#declaration)
+> *表达式* → [*表达式*](..\chapter3\04_Expressions.html#expression)
+> *表达式* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [条件列表](TODO)
+> *表达式* →
-### Do-While 语句
+### Repeat-While 语句
-`do-while`语句允许代码块被执行一次或多次。
+`repeat-while`语句允许代码块被执行一次或多次。
-`do-while`语句的形式如下:
+`repeat-while`语句的形式如下:
-> do {
+> repeat {
> `statements`
> } while `condition`
-`do-while`语句的执行流程如下:
+`repeat-while`语句的执行流程如下:
1. 执行 *statements*,然后转到第2步。
2. 计算 *condition* 表达式:
- 如果为`true`,转到第1步。如果为`false`,`do-while`至此执行完毕。
+ 如果为`true`,转到第1步。如果为`false`,`repeat-while`至此执行完毕。
-由于 *condition* 表达式的值是在 *statements* 执行后才计算出,因此`do-while`语句中的 *statements* 至少会被执行一次。
+由于 *condition* 表达式的值是在 *statements* 执行后才计算出,因此`repeat-while`语句中的 *statements* 至少会被执行一次。
-*condition* 表达式的值的类型必须遵循`LogicValue`协议。同时,*condition* 表达式也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
+*condition* 表达式的值的类型必须遵循`BooleanType `协议。同时,*condition* 表达式也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
-> Do-While 循环语法
-> *do-while语句* → **do** [*代码块*](..\chapter3\05_Declarations.html#code_block) **while** [*while条件*](..\chapter3\10_Statements.html#while_condition)
+> Repeat-While 循环语法
+> * repeat-while语句* → **repeat** [*代码块*](..\chapter3\05_Declarations.html#code_block) **while** [*while条件*](..\chapter3\10_Statements.html#while_condition)
## 分支语句
@@ -152,10 +156,10 @@
第二种形式是在第一种形式的基础上添加 *else 语句*,当只有一个 else 语句时,像下面这样:
-> if `condition` {
-> `statements to execute if condition is true`
-> } else {
-> `statements to execute if condition is false`
+> if `condition` {
+> `statements to execute if condition is true`
+> } else {
+> `statements to execute if condition is false`
> }
同时,else 语句也可包含`if`语句,从而形成一条链来测试更多的条件,像下面这样:
@@ -174,7 +178,28 @@
> If语句语法
> *if语句* → **if** [*if条件*](..\chapter3\10_Statements.html#if_condition) [*代码块*](..\chapter3\05_Declarations.html#code_block) [*else子句(Clause)*](..\chapter3\10_Statements.html#else_clause) _可选_
> *if条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*声明*](..\chapter3\05_Declarations.html#declaration)
-> *else子句(Clause)* → **else** [*代码块*](..\chapter3\05_Declarations.html#code_block) | **else** [*if语句*](..\chapter3\10_Statements.html#if_statement)
+> *else子句(Clause)* → **else** [*代码块*](..\chapter3\05_Declarations.html#code_block) | **else** [*if语句*](..\chapter3\10_Statements.html#if_statement)
+
+### Guard 语句
+
+`guard` 语句用来转移程序控制出该作用域,假如一个或者多个多个条件不成立。
+ `guard` 语句的格式如下:
+ > guard `condition` else {
+ `statements`
+ >}
+
+ `guard`语句中条件的值的类型必须遵循`LogicValue`协议。同时,条件也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
+
+ 在`guard`语句中声明的常量或者变量,可使用范围为从声明开始到作用域结束,常量和变量的值从可选绑定声明中分配。
+
+ `guard`语句需要有`else`子句,并且必须调用被`noreturn`属性标记的函数,或者使用下面的语句把程序执行转移到guard语句的作用域外。
+
+ * `return`
+ * `break`
+ * `continue`
+ * `throw`
+
+执行转移语句详情参见[执行转移语句](TODO)
### Switch 语句
@@ -226,11 +251,13 @@ case let (x, y) where x == y:
> *case标签* → **case** [*case项列表*](..\chapter3\10_Statements.html#case_item_list) **:**
> *case项列表* → [*模式*](..\chapter3\07_Patterns.html#pattern) [*guard-clause*](..\chapter3\10_Statements.html#guard_clause) _可选_ | [*模式*](..\chapter3\07_Patterns.html#pattern) [*guard-clause*](..\chapter3\10_Statements.html#guard_clause) _可选_ **,** [*case项列表*](..\chapter3\10_Statements.html#case_item_list)
> *default标签* → **default** **:**
-> *guard-clause* → **where** [*guard-expression*](..\chapter3\10_Statements.html#guard_expression)
-> *guard-expression* → [*表达式*](..\chapter3\04_Expressions.html#expression)
+> *where-clause* → **where** [*guard-expression*](..\chapter3\10_Statements.html#guard_expression)
+> *where-expression* → [*表达式*](..\chapter3\04_Expressions.html#expression)
- 带标签的语句
+
+
+## 带标签的语句
你可以在循环语句或`switch`语句前面加上*标签*,它由标签名和紧随其后的冒号(:)组成。在`break`和`continue`后面跟上标签名可以显式地在循环语句或`switch`语句中更改控制流,把控制权传递给指定标签标记的语句。关于这两条语句用法,详情参见 [Break 语句](#break_statement)和 [Continue 语句](#continue_statement)。
@@ -242,7 +269,8 @@ case let (x, y) where x == y:
> *标记语句(Labeled Statement)* → [*语句标签*](..\chapter3\10_Statements.html#statement_label) [*循环语句*](..\chapter3\10_Statements.html#loop_statement) | [*语句标签*](..\chapter3\10_Statements.html#statement_label) [*switch语句*](..\chapter3\10_Statements.html#switch_statement)
> *语句标签* → [*标签名称*](..\chapter3\10_Statements.html#label_name) **:**
> *标签名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
-
+
+
## 控制传递语句
通过无条件地把控制权从一片代码传递到另一片代码,控制传递语句能够改变代码执行的顺序。Swift 提供四种类型的控制传递语句:`break`语句、`continue`语句、`fallthrough`语句和`return`语句。
@@ -251,7 +279,8 @@ case let (x, y) where x == y:
> *控制传递语句* → [*break语句*](..\chapter3\10_Statements.html#break_statement)
> *控制传递语句* → [*continue语句*](..\chapter3\10_Statements.html#continue_statement)
> *控制传递语句* → [*fallthrough语句*](..\chapter3\10_Statements.html#fallthrough_statement)
-> *控制传递语句* → [*return语句*](..\chapter3\10_Statements.html#return_statement)
+> *控制传递语句* → [*return语句*](..\chapter3\10_Statements.html#return_statement)
+> *控制传递语句* → [*throw语句*](..\chapter3\10_Statements.html#throw_statement)
### Break 语句
@@ -303,8 +332,9 @@ case let (x, y) where x == y:
关于在`switch`语句中使用`fallthrough`语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的[控制传递语句](../chapter2/05_Control_Flow.html#control_transfer_statements)。
> Fallthrough 语句语法
-> *fallthrough语句* → **fallthrough**
+> *fallthrough语句* → **fallthrough**
+
### Return 语句
`return`语句用于在函数或方法的实现中将控制权传递给调用者,接着程序将会从调用者的位置继续向下执行。
@@ -319,4 +349,123 @@ case let (x, y) where x == y:
而当只写`return`时,仅仅是将控制权从该函数或方法传递给调用者,而不返回一个值。(这就是说,该函数或方法的返回类型为`Void`或`()`)
> Return 语句语法
-> *return语句* → **return** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_
+> *return语句* → **return** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_
+
+
+### Availability 语句
+
+可用性条件,被当做`if` ,`while` 语句的条件,并且 `guard` 语句在运行时会基于特定的语法格式查询接口的可用性。
+
+avaliability 语句的形式如下:
+> if #available(`platform name version`,` ...`, *) {
+> `statements to execute if the APIs are available`
+> } else {
+> `fallback statements to execute if the APIs are unavailable`
+> }
+
+可用性条件执行一个代码块时,取决于在运行时你想要使用的接口是否可用。
+当编译器检查到代码块中的接口是可用的,则从可用性条件中获取相应信息。
+
+可用性条件使用逗号分隔平台名称和版本列表。使用`iOS`,`OSX`,以及`watchOS`为平台名称,包括相应的版本号。*参数是必需的。在任何平台上代码块主体都被可用性条件保护起来,由目标规定的最小部署目标执行。
+
+与布尔类型条件不同,不能用逻辑运算符 **&&** 和 **||** 合并可用性条件。
+
+> 可用性条件语法
+> *可用性条件* → **#available** ( [availability-arguments](TODO) )
+> *可用性条件* → [availability-argument](TODO) | [availability-argument](TODO) , [availability-arguments](TODO)
+> *可用性条件* → [平台名称](TODO) [版本号](TODO)
+> *可用性条件* → **\***
+> *平台名称* → **iOS** | **iOSApplicationExtension**
+> *平台名称* → **OSX** | **OSXApplicationExtension**
+> *平台名称* → **watchOS**
+> *版本号* → [十进制数字](TODO)
+> *版本号* → [十进制数字](TODO) **.** [十进制数字](TODO)
+> *版本号* → [十进制数字](TODO) **.** [十进制数字](TODO) **.** [十进制数字](TODO)
+
+
+
+### Throw 语句
+`throw`语句出现在抛出函数或者抛出方法体内,或者类型被`throws`关键字标记的表达式体内。
+
+`throw`语句使程序结束执行当前的作用域,并在封闭作用域中传播错误。抛出的错误会一直传播,直到被`do`语句的`catch`子句处理掉。
+
+`throw`语句由`throw`关键字 跟一个表达式组成 ,如下所示。
+
+> throw `expression`
+
+表达式值的类型必须遵循 `LogicValue`协议
+
+关于如何使用`throw`语句的例子,详情参见[错误处理](TODO)一章的[抛出错误](TODO)。
+
+> throw 语句语法
+> *抛出语句* → **throw** *[表达式](TODO)*
+
+
+### Defer 语句
+
+ `defer` 语句用于转移程序控制出延迟语句作用域之前执行代码。
+
+在 `defer` 语句中的语句无论程序控制如何转移都会执行。这意味着 `defer` 语句可以被使用在以下这些情况,像手动得执行资源管理,关闭文件描述,或者即使抛出了错误也需要去实现执行一些动作。
+
+如果多个 `defer` 语句出现在同一范围内,那么它们执行的顺序与它们出现的顺序相反。最后执行的 `defer` 语句为给定范围内的第一个,这意味着最后的延迟语句中的语句涉及的资源可以被其他 `defer`语句清理掉。
+
+> 1 func f( ) {
+> 2 defer { print("First") }
+> 3 defer { print("Second") }
+> 4 defer { print("Third") }
+> 5 }
+> 6 f()
+> 7 // prints "Third"
+> 8 // prints "Second"
+> 9 // prints "First"
+
+
+`defer` 语句中的语句无法转移程序控制权出延迟语句。
+
+> defer 语句语法
+> *延迟语句* → **defer** *[代码块](TODO)*
+
+
+
+### Do 语句
+
+`do` 语句用于引入一个新的作用域,该作用域中可以含有一个或多个`catch`子句,catch子句中定义了一些匹配错误情况的模式。`do` 语句作用域内定义的常量和变量,只能在do语句作用域内访问。
+
+> do {
+> try `expression`
+> `statements`
+> } catch `pattern 1` {
+ `statements`
+> } catch `pattern 2` where condition {
+ `statements`
+> }
+
+
+如同`switch`语句,编译器会判断`catch`子句是否被遗漏。如果这样的决定被执行,则视为错误被处理。否则,错误会自动传播出包含作用域,被一个封闭的`catch`语句或抛出函数处理,包含函数必须以`throws`关键字声明。
+
+为了确保错误已经被处理,使用一个匹配所有错误的`catch`子句,如通配符模式(_)。如果一个`catch`子句不指定一种模式,catch子句会匹配和结合任何错误本地命名常量错误。有关可在catch子句中使用了图纹的更多信息,请参阅模式。
+
+为了确保错误已经被处理,使用一个匹配所有错误的`catch`子句,如通配符模式(_)。如果一个`catch`子句不指定一种模式,`catch`子句会匹配和约束任何局部变量命名的`error`。有关在`catch`子句中使用模式的更多信息,详见[模式](TODO)。
+
+关于在一些`catch`子句中如何使用` do`语句的例子,详情参见[错误处理](TODO)一章的[抛出错误](TODO)。
+
+> do 语句语法 → **do** *[代码块](TODO) [catch子句](TODO)*
+> catch子句 → *[catch子句](TODO) [catch子句](TODO)*
+> catch子句 → **catch** **[模式](TODO)** *可选的* [where子句]() *可选的* [代码块](TODO)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From 4c3a75e7907fff00972feb106509e209e08fcc3d Mon Sep 17 00:00:00 2001
From: futantan
Date: Mon, 29 Jun 2015 19:02:28 +0800
Subject: [PATCH 057/228] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=A4=BA=E4=BE=8B?=
=?UTF-8?q?=E4=BB=A3=E7=A0=81=20println()=20->=20print()?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 52 ++++++++++++++++-----------------
1 file changed, 26 insertions(+), 26 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index d17abb5d..dad93021 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -1,4 +1,4 @@
-> 翻译:[geek5nan](https://github.com/geek5nan)
+> 翻译:[geek5nan](https://github.com/geek5nan)
> 校对:[dabing1022](https://github.com/dabing1022)
# 协议
@@ -164,9 +164,9 @@ class LinearCongruentialGenerator: RandomNumberGenerator {
}
}
let generator = LinearCongruentialGenerator()
-println("Here's a random number: \(generator.random())")
+print("Here's a random number: \(generator.random())")
// 输出 : "Here's a random number: 0.37464991998171"
-println("And another one: \(generator.random())")
+print("And another one: \(generator.random())")
// 输出 : "And another one: 0.729023776863283"
```
@@ -178,7 +178,7 @@ println("And another one: \(generator.random())")
如果协议中的实例方法打算改变其`遵循者`实例的类型,那么在协议定义时需要在方法前加`mutating`关键字,才能使`结构体,枚举`来采用并满足协议中对方法的规定。
->注意:
+>注意:
>用`类`实现协议中的`mutating`方法时,不用写`mutating`关键字;用`结构体`,`枚举`实现协议中的`mutating`方法时,必须写`mutating`关键字。
如下所示,`Togglable`协议含有名为`toggle`的突变实例方法。根据名称推测,`toggle`方法应该是用于切换或恢复其`遵循者`实例或其属性的类型。
@@ -255,7 +255,7 @@ class SomeSuperClass {
}
}
-
+
class SomeSubClass: SomeSuperClass, SomeProtocol {
// "required" from SomeProtocol conformance; "override" from SomeSuperClass
required override init() {
@@ -277,7 +277,7 @@ class SomeSubClass: SomeSuperClass, SomeProtocol {
尽管`协议`本身并不实现任何功能,但是`协议`可以被当做类型来使用。
-使用场景:
+使用场景:
* `协议类型`作为函数、方法或构造器中的参数类型或返回值类型
* `协议类型`作为常量、变量或属性的类型
@@ -314,7 +314,7 @@ class Dice {
```swift
var d6 = Dice(sides: 6,generator: LinearCongruentialGenerator())
for _ in 1...5 {
- println("Random dice roll is \(d6.roll())")
+ print("Random dice roll is \(d6.roll())")
}
//输出结果
//Random dice roll is 3
@@ -333,7 +333,7 @@ for _ in 1...5 {
委托模式可以用来响应特定的动作或接收外部数据源提供的数据,而无需要知道外部数据源的所属类型(*译者注:只要求外部数据源`遵循`某协议*)。
-下文是两个基于骰子游戏的协议:
+下文是两个基于骰子游戏的协议:
```swift
protocol DiceGame {
@@ -349,7 +349,7 @@ protocol DiceGameDelegate {
```
`DiceGame`协议可以在任意含有骰子的游戏中实现,`DiceGameDelegate`协议可以用来追踪`DiceGame`的游戏过程
-
+
如下所示,`SnakesAndLadders`是`Snakes and Ladders`(译者注:[Control Flow](2)章节有该游戏的详细介绍)游戏的新版本。新版本使用`Dice`作为骰子,并且实现了`DiceGame`和`DiceGameDelegate`协议,后者用来记录游戏的过程:
```swift
@@ -403,16 +403,16 @@ class DiceGameTracker: DiceGameDelegate {
func gameDidStart(game: DiceGame) {
numberOfTurns = 0
if game is SnakesAndLadders {
- println("Started a new game of Snakes and Ladders")
+ print("Started a new game of Snakes and Ladders")
}
- println("The game is using a \(game.dice.sides)-sided dice")
+ print("The game is using a \(game.dice.sides)-sided dice")
}
func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
++numberOfTurns
- println("Rolled a \(diceRoll)")
+ print("Rolled a \(diceRoll)")
}
func gameDidEnd(game: DiceGame) {
- println("The game lasted for \(numberOfTurns) turns")
+ print("The game lasted for \(numberOfTurns) turns")
}
}
```
@@ -468,7 +468,7 @@ extension Dice: TextRepresentable {
```swift
let d12 = Dice(sides: 12,generator: LinearCongruentialGenerator())
-println(d12.asText())
+print(d12.asText())
// 输出 "A 12-sided dice"
```
@@ -480,7 +480,7 @@ extension SnakesAndLadders: TextRepresentable {
return "A game of Snakes and Ladders with \(finalSquare) squares"
}
}
-println(game.asText())
+print(game.asText())
// 输出 "A game of Snakes and Ladders with 25 squares"
```
@@ -504,7 +504,7 @@ extension Hamster: TextRepresentable {}
```swift
let simonTheHamster = Hamster(name: "Simon")
let somethingTextRepresentable: TextRepresentable = simonTheHamster
-println(somethingTextRepresentable.asText())
+print(somethingTextRepresentable.asText())
// 输出 "A hamster named Simon"
```
@@ -523,7 +523,7 @@ let things: [TextRepresentable] = [game,d12,simonTheHamster]
```swift
for thing in things {
- println(thing.asText())
+ print(thing.asText())
}
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
@@ -583,7 +583,7 @@ extension SnakesAndLadders: PrettyTextRepresentable {
任意`SankesAndLadders`的实例都可以使用`asPrettyText()`方法。
```swift
-println(game.asPrettyText())
+print(game.asPrettyText())
// A game of Snakes and Ladders with 25 squares:
// ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○
```
@@ -624,7 +624,7 @@ struct Person: Named, Aged {
var age: Int
}
func wishHappyBirthday(celebrator: protocol) {
- println("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")
+ print("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(birthdayPerson)
@@ -642,9 +642,9 @@ wishHappyBirthday(birthdayPerson)
使用`is`和`as`操作符来检查协议的一致性或转化协议类型。检查和转化的语法和之前相同(*详情查看[Typy Casting章节](5)*):
-* `is`操作符用来检查实例是否`遵循`了某个`协议`。
+* `is`操作符用来检查实例是否`遵循`了某个`协议`。
* `as?`返回一个可选值,当实例`遵循`协议时,返回该协议类型;否则返回`nil`
-* `as`用以强制向下转型。
+* `as`用以强制向下转型。
```swift
@objc protocol HasArea {
@@ -697,9 +697,9 @@ let objects: [AnyObject] = [
```swift
for object in objects {
if let objectWithArea = object as? HasArea {
- println("Area is \(objectWithArea.area)")
+ print("Area is \(objectWithArea.area)")
} else {
- println("Something that doesn't have an area")
+ print("Something that doesn't have an area")
}
}
// Area is 12.5663708
@@ -754,7 +754,7 @@ for object in objects {
`count`属性用于存储当前的值,`increment`方法用来为`count`赋值。
`increment`方法通过`可选链`,尝试从两种`可选成员`中获取`count`。
-
+
1. 由于`dataSource`可能为`nil`,因此在`dataSource`后边加上了`?`标记来表明只在`dataSource`非空时才去调用`incrementForCount`方法。
2. 即使`dataSource`存在,但是也无法保证其是否实现了`incrementForCount`方法,因此在`incrementForCount`方法后边也加有`?`标记
@@ -776,7 +776,7 @@ var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1...4 {
counter.increment()
- println(counter.count)
+ print(counter.count)
}
// 3
// 6
@@ -807,7 +807,7 @@ counter.count = -4
counter.dataSource = TowardsZeroSource()
for _ in 1...5 {
counter.increment()
- println(counter.count)
+ print(counter.count)
}
// -3
// -2
From 148004f1624d156827b1d01b61de68142f41cc11 Mon Sep 17 00:00:00 2001
From: futantan
Date: Mon, 29 Jun 2015 19:24:30 +0800
Subject: [PATCH 058/228] =?UTF-8?q?=E6=B7=BB=E5=8A=A02.0=E6=96=B0=E5=A2=9E?=
=?UTF-8?q?=E9=83=A8=E5=88=86=E7=9A=84=E8=8B=B1=E6=96=87=EF=BC=8C=E5=B9=B6?=
=?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=B7=BB=E5=8A=A0=E9=83=A8=E5=88=86=E7=9A=84?=
=?UTF-8?q?md=E6=A0=BC=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 76 +++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index dad93021..3e31a805 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -815,3 +815,79 @@ for _ in 1...5 {
// 0
// 0
```
+
+## Protocol Extensions
+
+Protocols can be extended to provide method and property implementations to conforming types. This allows you to define behavior on protocols themselves, rather than in each type’s individual conformance or in a global function.
+
+For example, the `RandomNumberGenerator` protocol can be extended to provide a `randomBool()` method, which uses the result of the required `random()` method to return a random `Bool` value:
+
+```swift
+extension RandomNumberGenerator {
+ func randomBool() -> Bool {
+ return random() > 0.5
+ }
+}
+```
+
+By creating an extension on the protocol, all conforming types automatically gain this method implementation without any additional modification.
+
+```swift
+let generator = LinearCongruentialGenerator()
+print("Here's a random number: \(generator.random())")
+// prints "Here's a random number: 0.37464991998171"
+print("And here's a random Boolean: \(generator.randomBool())")
+// prints "And here's a random Boolean: true"
+```
+
+### Providing Default Implementations
+
+You can use protocol extensions to provide a default implementation to any method or property requirement of that protocol. If a conforming type provides its own implementation of a required method or property, that implementation will be used instead of the one provided by the extension.
+
+> NOTE
+> Protocol requirements with default implementations provided by extensions are distinct from optional protocol requirements. Although conforming types don’t have to provide their own implementation of either, requirements with default implementations can be called without optional chaining.
+
+For example, the `PrettyTextRepresentable` protocol, which inherits the `TextRepresentable` protocol can provide a default implementation of its required `asPrettyText()` method to simply return the result of the `asText()` method:
+
+```swift
+extension PrettyTextRepresentable {
+ func asPrettyText() -> String {
+ return asText()
+ }
+}
+```
+
+### Adding Constraints to Protocol Extensions
+
+When you define a protocol extension, you can specify constraints that conforming types must satisfy before the methods and properties of the extension are available. You write these constraints after the name of the protocol you’re extending using a `where` clause, as described in ([Where 子句](TODO)).:
+
+For instance, you can define an extension to the `CollectionType` protocol that applies to any collection whose elements conform to the `TextRepresentable protocol` from the example above.
+
+```swift
+extension CollectionType where Generator.Element : TextRepresentable {
+ func asList() -> String {
+ return "(" + ", ".join(map({$0.asText()})) + ")"
+ }
+}
+```
+
+The `asList()` method takes the textual representation of each element in the collection and concatenates them into a comma-separated list.
+
+Consider the `Hamster` structure from before, which conforms to the `TextRepresentable` protocol, and an array of `Hamster` values:
+
+```swift
+let murrayTheHamster = Hamster(name: "Murray")
+let morganTheHamster = Hamster(name: "Morgan")
+let mauriceTheHamster = Hamster(name: "Maurice")
+let hamsters = [murrayTheHamster, morganTheHamster, mauriceTheHamster]
+```
+
+Because `Array` conforms to `CollectionType`, and the array’s elements conform to the `TextRepresentable` protocol, the array can use the `asList()` method to get a textual representation of its contents:
+
+```swift
+print(hamsters.asList())
+// prints "(A hamster named Murray, A hamster named Morgan, A hamster named Maurice)"
+```
+
+> NOTE
+> If a conforming type satisfies the requirements for multiple constrained extensions that provide implementations for the same method or property, Swift will use the implementation corresponding to the most specialized constraints.
From 97aaac1c2ca019f2a704e6f7c06cc112219e5b1b Mon Sep 17 00:00:00 2001
From: futantan
Date: Mon, 29 Jun 2015 19:34:04 +0800
Subject: [PATCH 059/228] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E5=86=85?=
=?UTF-8?q?=E5=AE=B9=E7=9A=84=E7=9B=AE=E5=BD=95=E8=B7=B3=E8=BD=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 3e31a805..6589399d 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -21,6 +21,8 @@
- [协议合成(Protocol Composition)](#protocol_composition)
- [检验协议的一致性(Checking for Protocol Conformance)](#checking_for_protocol_conformance)
- [对可选协议的规定(Optional Protocol Requirements)](#optional_protocol_requirements)
+- [协议扩展(Protocol Extensions)](#protocol_extensions)
+
`协议(Protocol)`用于定义完成某项任务或功能所必须的方法和属性,协议实际上并不提供这些功能或任务的具体`实现(Implementation)`--而只用来描述这些实现应该是什么样的。类,结构体,枚举通过提供协议所要求的方法,属性的具体实现来`采用(adopt)`协议。任意能够满足协议要求的类型被称为协议的`遵循者`。
@@ -816,7 +818,8 @@ for _ in 1...5 {
// 0
```
-## Protocol Extensions
+
+## 协议扩展
Protocols can be extended to provide method and property implementations to conforming types. This allows you to define behavior on protocols themselves, rather than in each type’s individual conformance or in a global function.
From 145e4fadc8f9130070db76106f825f00fb718176 Mon Sep 17 00:00:00 2001
From: futantan
Date: Fri, 3 Jul 2015 10:39:54 +0800
Subject: [PATCH 060/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E6=A6=82=E8=BF=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 6589399d..c8cdb814 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -24,9 +24,7 @@
- [协议扩展(Protocol Extensions)](#protocol_extensions)
-`协议(Protocol)`用于定义完成某项任务或功能所必须的方法和属性,协议实际上并不提供这些功能或任务的具体`实现(Implementation)`--而只用来描述这些实现应该是什么样的。类,结构体,枚举通过提供协议所要求的方法,属性的具体实现来`采用(adopt)`协议。任意能够满足协议要求的类型被称为协议的`遵循者`。
-
-`协议`可以要求其`遵循者`提供特定的实例属性,实例方法,类方法,操作符或下标脚本等。
+`协议`定义了一个蓝图,规定了用来实现某一特定工作或者功能所必需的方法和属性。类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能。任意能够满足协议要求的类型被称为`遵循(conform)`这个协议。
## 协议的语法
From 1b59383d6cafc0dd517b1edac2b0adbb32428273 Mon Sep 17 00:00:00 2001
From: futantan
Date: Fri, 3 Jul 2015 10:47:56 +0800
Subject: [PATCH 061/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90Proto?=
=?UTF-8?q?col=20Syntax?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index c8cdb814..e489cbe4 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -29,7 +29,7 @@
## 协议的语法
-`协议`的定义方式与`类,结构体,枚举`的定义都非常相似,如下所示:
+协议的定义方式与类,结构体,枚举的定义非常相似:
```swift
protocol SomeProtocol {
@@ -37,7 +37,7 @@ protocol SomeProtocol {
}
```
-在类型名称后加上`协议名称`,中间以冒号`:`分隔即可实现协议;实现多个协议时,各协议之间用逗号`,`分隔,如下所示:
+要使类遵循某个协议,需要在类型名称后加上协议名称,中间以冒号`:`分隔,作为类型定义的一部分。遵循多个协议时,各协议之间用逗号`,`分隔:
```swift
struct SomeStructure: FirstProtocol, AnotherProtocol {
@@ -45,7 +45,7 @@ struct SomeStructure: FirstProtocol, AnotherProtocol {
}
```
-如果一个类在含有`父类`的同时也采用了协议,应当把`父类`放在所有的`协议`之前,如下所示:
+如果类在遵循协议的同时拥有父类,应该将父类名放在协议名之前,以逗号分隔:
```swift
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
From 7e04e8d625c0c6600e85522796631c3eb768b533 Mon Sep 17 00:00:00 2001
From: futantan
Date: Fri, 3 Jul 2015 10:49:38 +0800
Subject: [PATCH 062/228] =?UTF-8?q?=E6=9B=B4=E6=94=B9Property=20Requiremen?=
=?UTF-8?q?ts=E7=BF=BB=E8=AF=91->=20=E5=B1=9E=E6=80=A7=E8=A6=81=E6=B1=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index e489cbe4..215a500f 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -7,7 +7,7 @@
本页包含内容:
- [协议的语法(Protocol Syntax)](#protocol_syntax)
-- [对属性的规定(Property Requirements)](#property_requirements)
+- [属性要求(Property Requirements)](#property_requirements)
- [对方法的规定(Method Requirements)](#method_requirements)
- [对突变方法的规定(Mutating Method Requirements)](#mutating_method_requirements)
- [对构造器的规定(Initializer Requirements)](#initializer_requirements)
@@ -54,7 +54,7 @@ class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
```
-## 对属性的规定
+## 属性要求
协议可以规定其`遵循者`提供特定名称与类型的`实例属性(instance property)`或`类属性(type property)`,而不管其是`存储型属性(stored property)`还是`计算型属性(calculate property)`。此外也可以指定属性是只读的还是可读写的。
From 9918eaf60898e77b648ea9498f2d1e4a0e44a235 Mon Sep 17 00:00:00 2001
From: futantan
Date: Fri, 3 Jul 2015 15:04:44 +0800
Subject: [PATCH 063/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E5=AF=B9=E5=B1=9E=E6=80=A7=E7=9A=84=E8=A7=84=E5=AE=9A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 57 +++++++++++++++++----------------
1 file changed, 29 insertions(+), 28 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 215a500f..ae226e8c 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -7,7 +7,7 @@
本页包含内容:
- [协议的语法(Protocol Syntax)](#protocol_syntax)
-- [属性要求(Property Requirements)](#property_requirements)
+- [对属性的规定(Property Requirements)](#property_requirements)
- [对方法的规定(Method Requirements)](#method_requirements)
- [对突变方法的规定(Mutating Method Requirements)](#mutating_method_requirements)
- [对构造器的规定(Initializer Requirements)](#initializer_requirements)
@@ -29,7 +29,7 @@
## 协议的语法
-协议的定义方式与类,结构体,枚举的定义非常相似:
+协议的定义方式与类,结构体,枚举的定义非常相似。
```swift
protocol SomeProtocol {
@@ -37,7 +37,7 @@ protocol SomeProtocol {
}
```
-要使类遵循某个协议,需要在类型名称后加上协议名称,中间以冒号`:`分隔,作为类型定义的一部分。遵循多个协议时,各协议之间用逗号`,`分隔:
+要使类遵循某个协议,需要在类型名称后加上协议名称,中间以冒号`:`分隔,作为类型定义的一部分。遵循多个协议时,各协议之间用逗号`,`分隔。
```swift
struct SomeStructure: FirstProtocol, AnotherProtocol {
@@ -45,7 +45,7 @@ struct SomeStructure: FirstProtocol, AnotherProtocol {
}
```
-如果类在遵循协议的同时拥有父类,应该将父类名放在协议名之前,以逗号分隔:
+如果类在遵循协议的同时拥有父类,应该将父类名放在协议名之前,以逗号分隔。
```swift
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
@@ -54,13 +54,13 @@ class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
```
-## 属性要求
+## 对属性的规定
-协议可以规定其`遵循者`提供特定名称与类型的`实例属性(instance property)`或`类属性(type property)`,而不管其是`存储型属性(stored property)`还是`计算型属性(calculate property)`。此外也可以指定属性是只读的还是可读写的。
+协议可以规定其`遵循者`提供特定名称和类型的`实例属性(instance property)`或`类属性(type property)`,而不指定是`存储型属性(stored property)`还是`计算型属性(calculate property)`。此外还必须指明是只读的还是可读可写的。
-如果协议要求属性是可读写的,那么这个属性不能是常量`存储型属性`或只读`计算型属性`;如果协议要求属性是只读的(gettable),那么`计算型属性`或`存储型属性`都能满足协议对属性的规定,在你的代码中,即使为只读属性实现了写方法(settable)也依然有效。
+如果协议要求属性是可读可写的,那么这个属性不能是常量或只读的计算属性。如果协议只要求属性是只读的(gettable),那个属性不仅可以是只读的,如果你代码需要的话,也可以是可写的。
-协议中的属性经常被加以`var`前缀声明其为变量属性,在声明后加上`{ set get }`来表示属性是可读写的,只读的属性则写作`{ get }`,如下所示:
+协议中的通常用var来声明属性,在类型声明后加上`{ set get }`来表示属性是可读可写的,只读属性则用`{ get }`来表示。
```swift
protocol SomeProtocol {
@@ -68,16 +68,17 @@ protocol SomeProtocol {
var doesNotNeedToBeSettable: Int { get }
}
```
-
-如下所示,通常在协议的定义中使用`class`前缀表示该属性为类成员;在枚举和结构体实现协议时中,需要使用`static`关键字作为前缀。
+
+在协议中定义类属性(type property)时,使用`static`关键字作为前缀。
+通常在协议的定义中使用`class`前缀表示该属性为类成员;在枚举和结构体实现协议时中,需要使用`static`关键字作为前缀。
```swift
protocol AnotherProtocol {
- class var someTypeProperty: Int { get set }
+ static var someTypeProperty: Int { get set }
}
```
-如下所示,这是一个含有一个实例属性要求的协议:
+如下所示,这是一个含有一个实例属性要求的协议。
```swift
protocol FullyNamed {
@@ -85,9 +86,9 @@ protocol FullyNamed {
}
```
-`FullyNamed`协议定义了任何拥有`fullName`的类型。它并不指定具体类型,而只是要求类型必须提供一个`fullName`。任何`FullyNamed`类型都得有一个只读的`fullName`属性,类型为`String`。
+`FullyNamed`协议除了要求协议的遵循者提供fullName属性外,对协议对遵循者的类型并没有特别的要求。这个协议表示,任何遵循`FullyNamed`协议的类型,都具有一个可读的`String`类型实例属性`fullName`。
-如下所示,这是一个实现了`FullyNamed`协议的简单结构体:
+下面是一个遵循`FullyNamed`协议的简单结构体。
```swift
struct Person: FullyNamed{
@@ -97,29 +98,29 @@ let john = Person(fullName: "John Appleseed")
//john.fullName 为 "John Appleseed"
```
-这个例子中定义了一个叫做`Person`的结构体,用来表示具有指定名字的人。从第一行代码中可以看出,它采用了`FullyNamed`协议。
+这个例子中定义了一个叫做`Person`的结构体,用来表示具有名字的人。从第一行代码中可以看出,它遵循了`FullyNamed`协议。
-`Person`结构体的每一个实例都有一个叫做`fullName`,`String`类型的存储型属性,这正好匹配了`FullyNamed`协议的要求,也就意味着,`Person`结构体完整的`遵循`了协议。(如果协议要求未被完全满足,在编译时会报错)
+`Person`结构体的每一个实例都有一个叫做`fullName`,`String`类型的存储型属性。这正好满足了`FullyNamed`协议的要求,也就意味着,`Person`结构体完整的`遵循`了协议。(如果协议要求未被完全满足,在编译时会报错)
-这有一个更为复杂的类,它采用并实现了`FullyNamed`协议,如下所示:
+下面是一个更为复杂的类,它采用并遵循了`FullyNamed`协议:
```swift
class Starship: FullyNamed {
- var prefix: String?
- var name: String
- init(name: String, prefix: String? = nil ) {
- self.name = name
- self.prefix = prefix
- }
- var fullName: String {
- return (prefix != nil ? prefix! + " " : " ") + name
- }
+ var prefix: String?
+ var name: String
+ init(name: String, prefix: String? = nil) {
+ self.name = name
+ self.prefix = prefix
+ }
+ var fullName: String {
+ return (prefix != nil ? prefix! + " " : "") + name
+ }
}
var ncc1701 = Starship(name: "Enterprise", prefix: "USS")
-// ncc1701.fullName == "USS Enterprise"
+// ncc1701.fullName is "USS Enterprise"
```
-`Starship`类把`fullName`属性实现为只读的`计算型属性`。每一个`Starship`类的实例都有一个名为`name`的必备属性和一个名为`prefix`的可选属性。 当`prefix`存在时,将`prefix`插入到`name`之前来为`Starship`构建`fullName`,`prefix`不存在时,则将直接用`name`构建`fullName`
+Starship类把`fullName`属性实现为只读的计算型属性。每一个`Starship`类的实例都有一个名为`name`的属性和一个名为`prefix`的可选属性。 当`prefix`存在时,将`prefix`插入到`name`之前来为Starship构建`fullName`,`prefix`不存在时,则将直接用`name`构建`fullName`。
## 对方法的规定
From 19e6b93d7897782d7d1cc418f65f64170ba07459 Mon Sep 17 00:00:00 2001
From: futantan
Date: Fri, 3 Jul 2015 15:40:11 +0800
Subject: [PATCH 064/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E5=AF=B9=E6=96=B9=E6=B3=95=E7=9A=84=E8=A7=84=E5=AE=9A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index ae226e8c..78d6e9bf 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -9,7 +9,7 @@
- [协议的语法(Protocol Syntax)](#protocol_syntax)
- [对属性的规定(Property Requirements)](#property_requirements)
- [对方法的规定(Method Requirements)](#method_requirements)
-- [对突变方法的规定(Mutating Method Requirements)](#mutating_method_requirements)
+- [对Mutating方法的规定(Mutating Method Requirements)](#mutating_method_requirements)
- [对构造器的规定(Initializer Requirements)](#initializer_requirements)
- [协议类型(Protocols as Types)](#protocols_as_types)
- [委托(代理)模式(Delegation)](#delegation)
@@ -68,9 +68,8 @@ protocol SomeProtocol {
var doesNotNeedToBeSettable: Int { get }
}
```
-
-在协议中定义类属性(type property)时,使用`static`关键字作为前缀。
-通常在协议的定义中使用`class`前缀表示该属性为类成员;在枚举和结构体实现协议时中,需要使用`static`关键字作为前缀。
+
+在协议中定义类属性(type property)时,总是使用`static`关键字作为前缀。当协议的遵循者是类时,可以使用`class`或`static`关键字来声明类属性,但是在协议的定义中,仍然要使用`static`关键字。
```swift
protocol AnotherProtocol {
@@ -125,20 +124,17 @@ Starship类把`fullName`属性实现为只读的计算型属性。每一个`Star
## 对方法的规定
-`协议`可以要求其`遵循者`实现某些指定的`实例方法`或`类方法`。这些方法作为协议的一部分,像普通的方法一样清晰的放在协议的定义中,而不需要大括号和方法体。
+协议可以要求其遵循者实现某些指定的实例方法或类方法。这些方法作为协议的一部分,像普通的方法一样放在协议的定义中,但是不需要大括号和方法体。可以在协议中定义具有可变参数的方法,和普通方法的定义方式相同。但是在协议的方法定义中,不支持参数默认值。
->注意:
->协议中的方法支持`变长参数(variadic parameter)`,不支持`参数默认值(default value)`。
-
-如下所示,协议中类方法的定义与类属性的定义相似,在协议定义的方法前置`class`关键字来表示。当在`枚举`或`结构体`实现类方法时,需要使用`static`关键字来代替。
+正如对属性的规定中所说的,在协议中定义类方法的时候,总是使用`static`关键字作为前缀。当协议的遵循者是类的时候,虽然你可以在类的实现中使用`class`或者`static`来实现类方法,但是在协议中声明类方法,仍然要使用`static`关键字。
```swift
protocol SomeProtocol {
- class func someTypeMethod()
+ static func someTypeMethod()
}
```
-如下所示,定义了含有一个实例方法的的协议。
+下面的例子定义了含有一个实例方法的协议。
```swift
protocol RandomNumberGenerator {
@@ -146,7 +142,7 @@ protocol RandomNumberGenerator {
}
```
-`RandomNumberGenerator`协议要求其`遵循者`必须拥有一个名为`random`, 返回值类型为`Double`的实例方法。 (尽管这里并未指明,但是我们假设返回值在[0,1]区间内)。
+`RandomNumberGenerator`协议要求其遵循者必须拥有一个名为`random`, 返回值类型为`Double`的实例方法。尽管这里并未指明,但是我们假设返回值在[0,1)区间内。
`RandomNumberGenerator`协议并不在意每一个随机数是怎样生成的,它只强调这里有一个随机数生成器。
@@ -172,7 +168,7 @@ print("And another one: \(generator.random())")
```
-## 对突变方法的规定
+## 对Mutating方法的规定
有时不得不在方法中更改实例的所属类型。在基于`值类型(value types)`(结构体,枚举)的实例方法中,将`mutating`关键字作为函数的前缀,写在`func`之前,表示可以在该方法中修改实例及其属性的所属类型。这一过程在[Modifyting Value Types from Within Instance Methods](1)章节中有详细描述。
From c6b818a4e11333805eb7cdd7a42c3e3bef8889ee Mon Sep 17 00:00:00 2001
From: futantan
Date: Fri, 3 Jul 2015 16:19:41 +0800
Subject: [PATCH 065/228] =?UTF-8?q?Protocols=20-=20=E5=AF=B9Mutating?=
=?UTF-8?q?=E6=96=B9=E6=B3=95=E7=9A=84=E8=A7=84=E5=AE=9A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 78d6e9bf..24a56bfa 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -170,15 +170,17 @@ print("And another one: \(generator.random())")
## 对Mutating方法的规定
-有时不得不在方法中更改实例的所属类型。在基于`值类型(value types)`(结构体,枚举)的实例方法中,将`mutating`关键字作为函数的前缀,写在`func`之前,表示可以在该方法中修改实例及其属性的所属类型。这一过程在[Modifyting Value Types from Within Instance Methods](1)章节中有详细描述。
+有时需要在方法中改变它的实例。例如,值类型(结构体,枚举)的实例方法中,将`mutating`关键字作为函数的前缀,写在`func`之前,表示可以在该方法中修改它所属的实例及其实例属性的值。这一过程在[Modifyting Value Types from Within Instance Methods](TODO)章节中有详细描述。
-如果协议中的实例方法打算改变其`遵循者`实例的类型,那么在协议定义时需要在方法前加`mutating`关键字,才能使`结构体,枚举`来采用并满足协议中对方法的规定。
+如果你在协议中定义了一个方法旨在改变遵循该协议的实例,那么在协议定义时需要在方法前加`mutating`关键字。这使得结构和枚举遵循协议并满足此方法要求。
>注意:
->用`类`实现协议中的`mutating`方法时,不用写`mutating`关键字;用`结构体`,`枚举`实现协议中的`mutating`方法时,必须写`mutating`关键字。
+>用类实现协议中的`mutating`方法时,不用写`mutating`关键字;用结构体,枚举实现协议中的`mutating`方法时,必须写`mutating`关键字。
-如下所示,`Togglable`协议含有名为`toggle`的突变实例方法。根据名称推测,`toggle`方法应该是用于切换或恢复其`遵循者`实例或其属性的类型。
+如下所示,`Togglable`协议含有名为`toggle`的实例方法。根据名称推测,`toggle()`方法将通过改变实例属性,来切换遵循该协议的实例的状态。
+
+`toggle()`方法在定义的时候,使用`mutating`关键字标记,这表明当它被调用时该方法将会改变协议遵循者实例的状态。
```swift
protocol Togglable {
@@ -186,9 +188,9 @@ protocol Togglable {
}
```
-当使用`枚举`或`结构体`来实现`Togglabl`协议时,需要提供一个带有`mutating`前缀的`toggle`方法。
+当使用`枚举`或`结构体`来实现`Togglable`协议时,需要提供一个带有`mutating`前缀的`toggle`方法。
-如下所示,`OnOffSwitch`枚举`遵循`了`Togglable`协议,`On`,`Off`两个成员用于表示当前状态。枚举的`toggle`方法被标记为`mutating`,用以匹配`Togglabel`协议的规定。
+下面定义了一个名为`OnOffSwitch`的枚举类型。这个枚举类型在两种状态之间进行切换,用枚举成员`On`和`Off`表示。枚举类型的`toggle`方法被标记为`mutating`以满足`Togglable`协议的要求。
```swift
enum OnOffSwitch: Togglable {
@@ -218,7 +220,7 @@ protocol SomeProtocol {
}
```
-**协议构造器规定在类中的实现**
+### 协议构造器规定在类中的实现
你可以在遵循该协议的类中实现构造器,并指定其为类的特定构造器或者便捷构造器。在这两种情况下,你都必须给构造器实现标上"required"修饰符:
From 59883d153ae163ce6e7f08f9dbc1960a818cf868 Mon Sep 17 00:00:00 2001
From: futantan
Date: Fri, 3 Jul 2015 16:20:42 +0800
Subject: [PATCH 066/228] =?UTF-8?q?Protocols=20-=20=E4=BF=AE=E6=94=B9?=
=?UTF-8?q?=E4=BA=8C=E7=BA=A7=E6=A0=87=E9=A2=98markdown=E8=AF=AD=E6=B3=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 24a56bfa..e4cd628a 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -263,7 +263,7 @@ class SomeSubClass: SomeSuperClass, SomeProtocol {
}
```
-**可失败构造器的规定**
+### 可失败构造器的规定
可以通过给协议```Protocols```中添加可失败构造器来使遵循该协议的类型必须实现该可失败构造器。
From 0a097be9a2b6e2abd9a870de34019d5291e05e91 Mon Sep 17 00:00:00 2001
From: futantan
Date: Sat, 4 Jul 2015 09:27:05 +0800
Subject: [PATCH 067/228] =?UTF-8?q?Protocols=20-=20=E5=AF=B9=E6=9E=84?=
=?UTF-8?q?=E9=80=A0=E5=99=A8=E7=9A=84=E8=A7=84=E5=AE=9A=20=E7=BB=BC?=
=?UTF-8?q?=E8=BF=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index e4cd628a..01e68099 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -212,7 +212,7 @@ lightSwitch.toggle()
## 对构造器的规定
-协议可以要求它的遵循类型实现特定的构造器。你可以像书写普通的构造器那样,在协议的定义里写下构造器的需求,但不需要写花括号和构造器的实体:
+协议可以要求它的遵循者实现指定的构造器。你可以像书写普通的构造器那样,在协议的定义里写下构造器的声明,但不需要写花括号和构造器的实体:
```swift
protocol SomeProtocol {
From ffe3303ba48f216c7b703bf8b5527f905350baf5 Mon Sep 17 00:00:00 2001
From: futantan
Date: Sat, 4 Jul 2015 09:50:10 +0800
Subject: [PATCH 068/228] =?UTF-8?q?Protocols=20-=20=E5=AF=B9=E6=9E=84?=
=?UTF-8?q?=E9=80=A0=E5=99=A8=E7=9A=84=E8=A7=84=E5=AE=9A=20=E5=8D=8F?=
=?UTF-8?q?=E8=AE=AE=E6=9E=84=E9=80=A0=E5=99=A8=E8=A7=84=E5=AE=9A=E5=9C=A8?=
=?UTF-8?q?=E7=B1=BB=E4=B8=AD=E7=9A=84=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 01e68099..8aeb1373 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -222,7 +222,7 @@ protocol SomeProtocol {
### 协议构造器规定在类中的实现
-你可以在遵循该协议的类中实现构造器,并指定其为类的特定构造器或者便捷构造器。在这两种情况下,你都必须给构造器实现标上"required"修饰符:
+你可以在遵循该协议的类中实现构造器,并指定其为类的指定构造器(designated initializer)或者便利构造器(convenience initializer)。在这两种情况下,你都必须给构造器实现标上"required"修饰符:
```swift
class SomeClass: SomeProtocol {
@@ -234,11 +234,12 @@ class SomeClass: SomeProtocol {
使用`required`修饰符可以保证:所有的遵循该协议的子类,同样能为构造器规定提供一个显式的实现或继承实现。
-关于`required`构造器的更多内容,请参考`required`构造器
+
+关于`required`构造器的更多内容,请参考`Required`构造器
+
>注意
->
->如果类已经被“final”修饰符所标示,你就不需要在协议构造器规定的实现中使用"required"修饰符。因为final类不能有子类。关于`final`修饰符的更多内容,请参见防止重写
+>如果类已经被标记为`final`,那么不需要在协议构造器的实现中使用`required`修饰符。因为final类不能有子类。关于`final`修饰符的更多内容,请参见防止重写
如果一个子类重写了父类的指定构造器,并且该构造器遵循了某个协议的规定,那么该构造器的实现需要被同时标示`required`和`override`修饰符
@@ -250,13 +251,13 @@ protocol SomeProtocol {
class SomeSuperClass {
init() {
- //协议定义
+ // 构造器的实现
}
}
class SomeSubClass: SomeSuperClass, SomeProtocol {
- // "required" from SomeProtocol conformance; "override" from SomeSuperClass
+ // 因为遵循协议,需要加上"required"; 因为继承自父类,需要加上"override"
required override init() {
// 构造器实现
}
@@ -265,7 +266,7 @@ class SomeSubClass: SomeSuperClass, SomeProtocol {
### 可失败构造器的规定
-可以通过给协议```Protocols```中添加可失败构造器来使遵循该协议的类型必须实现该可失败构造器。
+可以通过给协议`Protocols`中添加可失败构造器来使遵循该协议的类型必须实现该可失败构造器。
如果在协议中定义一个可失败构造器,则在遵顼该协议的类型中必须添加同名同参数的可失败构造器或非可失败构造器。
如果在协议中定义一个非可失败构造器,则在遵循该协议的类型中必须添加同名同参数的非可失败构造器或隐式解析类型的可失败构造器(`init!`)。
From 68b6028ee15fc662b5a2e74f88434fb808d2728e Mon Sep 17 00:00:00 2001
From: futantan
Date: Sat, 4 Jul 2015 09:57:20 +0800
Subject: [PATCH 069/228] =?UTF-8?q?Protocols=20-=20=E5=AF=B9=E6=9E=84?=
=?UTF-8?q?=E9=80=A0=E5=99=A8=E7=9A=84=E8=A7=84=E5=AE=9A=20=E5=8F=AF?=
=?UTF-8?q?=E5=A4=B1=E8=B4=A5=E6=9E=84=E9=80=A0=E5=99=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 8aeb1373..5f3f5dc2 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -268,8 +268,7 @@ class SomeSubClass: SomeSuperClass, SomeProtocol {
可以通过给协议`Protocols`中添加可失败构造器来使遵循该协议的类型必须实现该可失败构造器。
-如果在协议中定义一个可失败构造器,则在遵顼该协议的类型中必须添加同名同参数的可失败构造器或非可失败构造器。
-如果在协议中定义一个非可失败构造器,则在遵循该协议的类型中必须添加同名同参数的非可失败构造器或隐式解析类型的可失败构造器(`init!`)。
+如果在协议中定义一个可失败构造器,则在遵顼该协议的类型中必须添加同名同参数的可失败构造器或非可失败构造器。如果在协议中定义一个非可失败构造器,则在遵循该协议的类型中必须添加同名同参数的非可失败构造器或隐式解析类型的可失败构造器(`init!`)。
From a51a21f2f32b9da931c3c1b2fd67df6e69b802f0 Mon Sep 17 00:00:00 2001
From: futantan
Date: Sat, 4 Jul 2015 10:14:16 +0800
Subject: [PATCH 070/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90=20?=
=?UTF-8?q?=E5=8D=8F=E8=AE=AE=E7=B1=BB=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 5f3f5dc2..455f0db2 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -274,15 +274,16 @@ class SomeSubClass: SomeSuperClass, SomeProtocol {
## 协议类型
-尽管`协议`本身并不实现任何功能,但是`协议`可以被当做类型来使用。
+尽管协议本身并不实现任何功能,但是协议可以被当做类型来使用。
-使用场景:
+协议可以像其他普通类型一样使用,使用场景:
-* `协议类型`作为函数、方法或构造器中的参数类型或返回值类型
-* `协议类型`作为常量、变量或属性的类型
-* `协议类型`作为数组、字典或其他容器中的元素类型
+* 作为函数、方法或构造器中的参数类型或返回值类型
+* 作为常量、变量或属性的类型
+* 作为数组、字典或其他容器中的元素类型
-> 注意: 协议是一种类型,因此协议类型的名称应与其他类型(Int,Double,String)的写法相同,使用驼峰式写法
+> 注意
+> 协议是一种类型,因此协议类型的名称应与其他类型(Int,Double,String)的写法相同,使用大写字母开头的驼峰式写法,例如(`FullyNamed`和`RandomNumberGenerator`)
如下所示,这个示例中将协议当做类型来使用
@@ -300,18 +301,18 @@ class Dice {
}
```
-例子中又一个`Dice`类,用来代表桌游中的拥有N个面的骰子。`Dice`的实例含有`sides`和`generator`两个属性,前者是整型,用来表示骰子有几个面,后者为骰子提供一个随机数生成器。
+例子中定义了一个`Dice`类,用来代表桌游中的拥有N个面的骰子。`Dice`的实例含有`sides`和`generator`两个属性,前者是整型,用来表示骰子有几个面,后者为骰子提供一个随机数生成器。
`generator`属性的类型为`RandomNumberGenerator`,因此任何遵循了`RandomNumberGenerator`协议的类型的实例都可以赋值给`generator`,除此之外,无其他要求。
-`Dice`类中也有一个`构造器(initializer)`,用来进行初始化操作。构造器中含有一个名为`generator`,类型为`RandomNumberGenerator`的形参。在调用构造方法时创建`Dice`的实例时,可以传入任何遵循`RandomNumberGenerator`协议的实例给generator。
+`Dice`类中也有一个构造器(initializer),用来进行初始化操作。构造器中含有一个名为`generator`,类型为`RandomNumberGenerator`的形参。在调用构造方法时创建`Dice`的实例时,可以传入任何遵循`RandomNumberGenerator`协议的实例给generator。
-`Dice`类也提供了一个名为`roll`的实例方法用来模拟骰子的面值。它先使用`generator`的`random`方法来创建一个[0-1]区间内的随机数种子,然后加工这个随机数种子生成骰子的面值。generator被认为是遵循了`RandomNumberGenerator`的类型,因而保证了`random`方法可以被调用。
+`Dice`类也提供了一个名为`roll`的实例方法用来模拟骰子的面值。它先使用`generator`的`random()`方法来创建一个[0,1)区间内的随机数,然后使用这个随机数生成正确的骰子面值。因为generator遵循了`RandomNumberGenerator`协议,因而保证了`random`方法可以被调用。
-如下所示,这里展示了如何使用`LinearCongruentialGenerator`的实例作为随机数生成器创建一个六面骰子:
+下面的例子展示了如何使用`LinearCongruentialGenerator`的实例作为随机数生成器创建一个六面骰子:
```swift
-var d6 = Dice(sides: 6,generator: LinearCongruentialGenerator())
+var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
for _ in 1...5 {
print("Random dice roll is \(d6.roll())")
}
From a8ec9464bd88fea0caf9b12089a5e83daaa96460 Mon Sep 17 00:00:00 2001
From: futantan
Date: Sat, 4 Jul 2015 10:51:06 +0800
Subject: [PATCH 071/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E5=A7=94=E6=89=98(=E4=BB=A3=E7=90=86)=E6=A8=A1=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 455f0db2..a5828e9f 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -327,13 +327,9 @@ for _ in 1...5 {
## 委托(代理)模式
-委托是一种设计模式(*译者注: 想起了那年 UITableViewDelegate 中的奔跑,那是我逝去的Objective-C。。。*),它允许`类`或`结构体`将一些需要它们负责的功能`交由(委托)`给其他的类型的实例。
+委托是一种设计模式,它允许`类`或`结构体`将一些需要它们负责的功能`交由(委托)`给其他的类型的实例。委托模式的实现很简单: 定义协议来封装那些需要被委托的函数和方法, 使其`遵循者`拥有这些被委托的`函数和方法`。委托模式可以用来响应特定的动作或接收外部数据源提供的数据,而无需要知道外部数据源的类型信息。
-委托模式的实现很简单: 定义`协议`来`封装`那些需要被委托的`函数和方法`, 使其`遵循者`拥有这些被委托的`函数和方法`。
-
-委托模式可以用来响应特定的动作或接收外部数据源提供的数据,而无需要知道外部数据源的所属类型(*译者注:只要求外部数据源`遵循`某协议*)。
-
-下文是两个基于骰子游戏的协议:
+下面的例子是两个基于骰子游戏的协议:
```swift
protocol DiceGame {
@@ -348,7 +344,7 @@ protocol DiceGameDelegate {
}
```
-`DiceGame`协议可以在任意含有骰子的游戏中实现,`DiceGameDelegate`协议可以用来追踪`DiceGame`的游戏过程
+`DiceGame`协议可以在任意含有骰子的游戏中实现。`DiceGameDelegate`协议可以用来追踪`DiceGame`的游戏过程
如下所示,`SnakesAndLadders`是`Snakes and Ladders`(译者注:[Control Flow](2)章节有该游戏的详细介绍)游戏的新版本。新版本使用`Dice`作为骰子,并且实现了`DiceGame`和`DiceGameDelegate`协议,后者用来记录游戏的过程:
@@ -385,15 +381,15 @@ class SnakesAndLadders: DiceGame {
}
```
-这个版本的游戏封装到了`SnakesAndLadders`类中,该类采用了`DiceGame`协议,并且提供了`dice`属性和`play`实例方法用来`遵循`协议。(`dice`属性在构造之后就不在改变,且协议只要求`dice`为只读的,因此将`dice`声明为常量属性。)
+这个版本的游戏封装到了`SnakesAndLadders`类中,该类遵循了`DiceGame`协议,并且提供了相应的可读的`dice`属性和`play`实例方法。(`dice`属性在构造之后就不再改变,且协议只要求`dice`为只读的,因此将`dice`声明为常量属性。)
在`SnakesAndLadders`类的`构造器(initializer)`初始化游戏。所有的游戏逻辑被转移到了`play`方法中,`play`方法使用协议规定的`dice`属性提供骰子摇出的值。
-> 注意:`delegate`并不是游戏的必备条件,因此`delegate`被定义为遵循`DiceGameDelegate`协议的可选属性,`delegate`使用`nil`作为初始值。
+注意:`delegate`并不是游戏的必备条件,因此`delegate`被定义为遵循`DiceGameDelegate`协议的可选属性。因为`delegate`是可选值,因此在初始化的时候被自动赋值为`nil`。随后,可以在游戏中为`delegate`设置适当的值。
`DicegameDelegate`协议提供了三个方法用来追踪游戏过程。被放置于游戏的逻辑中,即`play()`方法内。分别在游戏开始时,新一轮开始时,游戏结束时被调用。
-因为`delegate`是一个遵循`DiceGameDelegate`的可选属性,因此在`play()`方法中使用了`可选链`来调用委托方法。 若`delegate`属性为`nil`, 则delegate所调用的方法失效。若`delegate`不为`nil`,则方法能够被调用
+因为`delegate`是一个遵循`DiceGameDelegate`的可选属性,因此在`play()`方法中使用了`可选链`来调用委托方法。 若`delegate`属性为`nil`, 则delegate所调用的方法失效,并不会产生错误。若`delegate`不为`nil`,则方法能够被调用
如下所示,`DiceGameTracker`遵循了`DiceGameDelegate`协议
From 4a7fedf46e999e21a13a23b932ca5ab46af59d41 Mon Sep 17 00:00:00 2001
From: futantan
Date: Sat, 4 Jul 2015 20:10:44 +0800
Subject: [PATCH 072/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E5=A7=94=E6=89=98(=E4=BB=A3=E7=90=86)=E6=A8=A1=E5=BC=8F=20?=
=?UTF-8?q?=E6=A0=A1=E5=AF=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index a5828e9f..0b9fc63b 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -383,7 +383,7 @@ class SnakesAndLadders: DiceGame {
这个版本的游戏封装到了`SnakesAndLadders`类中,该类遵循了`DiceGame`协议,并且提供了相应的可读的`dice`属性和`play`实例方法。(`dice`属性在构造之后就不再改变,且协议只要求`dice`为只读的,因此将`dice`声明为常量属性。)
-在`SnakesAndLadders`类的`构造器(initializer)`初始化游戏。所有的游戏逻辑被转移到了`play`方法中,`play`方法使用协议规定的`dice`属性提供骰子摇出的值。
+游戏使用`SnakesAndLadders`类的`构造器(initializer)`初始化游戏。所有的游戏逻辑被转移到了协议中的`play`方法,`play`方法使用协议规定的`dice`属性提供骰子摇出的值。
注意:`delegate`并不是游戏的必备条件,因此`delegate`被定义为遵循`DiceGameDelegate`协议的可选属性。因为`delegate`是可选值,因此在初始化的时候被自动赋值为`nil`。随后,可以在游戏中为`delegate`设置适当的值。
@@ -413,7 +413,7 @@ class DiceGameTracker: DiceGameDelegate {
}
```
-`DiceGameTracker`实现了`DiceGameDelegate`协议规定的三个方法,用来记录游戏已经进行的轮数。 当游戏开始时,`numberOfTurns`属性被赋值为0; 在每新一轮中递加; 游戏结束后,输出打印游戏的总轮数。
+`DiceGameTracker`实现了`DiceGameDelegate`协议规定的三个方法,用来记录游戏已经进行的轮数。 当游戏开始时,`numberOfTurns`属性被赋值为0; 在每新一轮中递增; 游戏结束后,输出打印游戏的总轮数。
`gameDidStart`方法从`game`参数获取游戏信息并输出。`game`在方法中被当做`DiceGame`类型而不是`SnakeAndLadders`类型,所以方法中只能访问`DiceGame`协议中的成员。当然了,这些方法也可以在类型转换之后调用。在上例代码中,通过`is`操作符检查`game`是否为 `SnakesAndLadders`类型的实例,如果是,则打印出相应的内容。
From 857dcd619a4da1b190f721e8e5374e811bd90c33 Mon Sep 17 00:00:00 2001
From: futantan
Date: Sat, 4 Jul 2015 20:27:43 +0800
Subject: [PATCH 073/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E5=9C=A8=E6=89=A9=E5=B1=95=E4=B8=AD=E6=B7=BB=E5=8A=A0=E5=8D=8F?=
=?UTF-8?q?=E8=AE=AE=E6=88=90=E5=91=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 0b9fc63b..b09b6335 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -417,7 +417,7 @@ class DiceGameTracker: DiceGameDelegate {
`gameDidStart`方法从`game`参数获取游戏信息并输出。`game`在方法中被当做`DiceGame`类型而不是`SnakeAndLadders`类型,所以方法中只能访问`DiceGame`协议中的成员。当然了,这些方法也可以在类型转换之后调用。在上例代码中,通过`is`操作符检查`game`是否为 `SnakesAndLadders`类型的实例,如果是,则打印出相应的内容。
-无论当前进行的是何种游戏,`game`都遵循`DiceGame`协议以确保`game`含有`dice`属性,因此在`gameDidStart`方法中可以通过传入的`game`参数来访问`dice`属性,进而打印出`dice`的`sides`属性的值。
+无论当前进行的是何种游戏,`game`都遵循`DiceGame`协议以确保`game`含有`dice`属性,因此在`gameDidStart(_:)`方法中可以通过传入的`game`参数来访问`dice`属性,进而打印出`dice`的`sides`属性的值。
`DiceGameTracker`的运行情况,如下所示:
@@ -438,11 +438,12 @@ game.play()
## 在扩展中添加协议成员
-即便无法修改源代码,依然可以通过`扩展(Extension)`来扩充已存在类型(*译者注: 类,结构体,枚举等*)。`扩展`可以为已存在的类型添加`属性`,`方法`,`下标脚本`,`协议`等成员。详情请在[扩展](4)章节中查看。
+即便无法修改源代码,依然可以通过扩展(Extension)来扩充已存在类型(*译者注: 类,结构体,枚举等*)。扩展可以为已存在的类型添加属性,方法,下标脚本,协议等成员。详情请在[扩展](4)章节中查看。
-> 注意: 通过`扩展`为已存在的类型`遵循`协议时,该类型的所有实例也会随之添加协议中的方法
+> 注意
+> 通过扩展为已存在的类型遵循协议时,该类型的所有实例也会随之添加协议中的方法
-`TextRepresentable`协议含有一个`asText`,如下所示:
+例如`TextRepresentable`协议,任何想要表示一些文本内容的类型都可以遵循该协议。这些想要表示的内容可以是类型本身的描述,也可以是当前内容的版本:
```swift
protocol TextRepresentable {
@@ -450,7 +451,7 @@ protocol TextRepresentable {
}
```
-通过`扩展`为上一节中提到的`Dice`类遵循`TextRepresentable`协议
+可以通过扩展,为上一节中提到的`Dice`增加类遵循`TextRepresentable`协议的功能
```swift
extension Dice: TextRepresentable {
@@ -459,8 +460,9 @@ extension Dice: TextRepresentable {
}
}
```
+现在,通过扩展使得`Dice`类型遵循了一个新的协议,这和`Dice`类型在定义的时候声明为遵循`TextRepresentable`协议的效果相同。在扩展的时候,协议名称写在类型名之后,以冒号隔开,在大括号内写明新添加的协议内容。
-从现在起,`Dice`类型的实例可被当作`TextRepresentable`类型:
+现在所有`Dice`的实例都遵循了`TextRepresentable`协议:
```swift
let d12 = Dice(sides: 12,generator: LinearCongruentialGenerator())
@@ -468,7 +470,7 @@ print(d12.asText())
// 输出 "A 12-sided dice"
```
-`SnakesAndLadders`类也可以通过`扩展`的方式来遵循协议:
+同样`SnakesAndLadders`类也可以通过`扩展`的方式来遵循`TextRepresentable`协议:
```swift
extension SnakesAndLadders: TextRepresentable {
From 866097add001d2f7c9b7f3c912b4c86c33a0f088 Mon Sep 17 00:00:00 2001
From: futantan
Date: Sat, 4 Jul 2015 20:31:06 +0800
Subject: [PATCH 074/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E9=80=9A=E8=BF=87=E6=89=A9=E5=B1=95=E8=A1=A5=E5=85=85=E5=8D=8F?=
=?UTF-8?q?=E8=AE=AE=E5=A3=B0=E6=98=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index b09b6335..7ca35ac4 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -485,7 +485,7 @@ print(game.asText())
## 通过扩展补充协议声明
-当一个类型已经实现了协议中的所有要求,却没有声明时,可以通过`扩展`来补充协议声明:
+当一个类型已经实现了协议中的所有要求,却没有声明为遵循该协议时,可以通过扩展(空的扩展体)来补充协议声明:
```swift
struct Hamster {
@@ -506,7 +506,8 @@ print(somethingTextRepresentable.asText())
// 输出 "A hamster named Simon"
```
-> 注意: 即使满足了协议的所有要求,类型也不会自动转变,因此你必须为它做出明显的协议声明
+> 注意
+> 即使满足了协议的所有要求,类型也不会自动转变,因此你必须为它做出显式的协议声明
## 集合中的协议类型
From 17751155281e0bf8b0ce8183b8df28c487e8fefa Mon Sep 17 00:00:00 2001
From: futantan
Date: Sat, 4 Jul 2015 20:55:07 +0800
Subject: [PATCH 075/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E9=9B=86=E5=90=88=E4=B8=AD=E7=9A=84=E5=8D=8F=E8=AE=AE=E7=B1=BB?=
=?UTF-8?q?=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index 7ca35ac4..f9aaa911 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -512,13 +512,13 @@ print(somethingTextRepresentable.asText())
## 集合中的协议类型
-协议类型可以被集合使用,表示集合中的元素均为协议类型:
+协议类型可以在集合使用,表示集合中的元素均为协议类型,下面的例子创建了一个类型为`TextRepresentable`的数组:
```swift
let things: [TextRepresentable] = [game,d12,simonTheHamster]
```
-如下所示,`things`数组可以被直接遍历,并调用其中元素的`asText()`函数:
+如下所示,`things`数组可以被直接遍历,并打印每个元素的文本表示:
```swift
for thing in things {
From 6062b84363714e2573bfbb79500b7a5839478a28 Mon Sep 17 00:00:00 2001
From: futantan
Date: Sat, 4 Jul 2015 21:24:35 +0800
Subject: [PATCH 076/228] =?UTF-8?q?Protocols=20-=20=E5=AE=8C=E6=88=90?=
=?UTF-8?q?=E5=8D=8F=E8=AE=AE=E7=9A=84=E7=BB=A7=E6=89=BF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/22_Protocols.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/source/chapter2/22_Protocols.md b/source/chapter2/22_Protocols.md
index f9aaa911..0933d597 100644
--- a/source/chapter2/22_Protocols.md
+++ b/source/chapter2/22_Protocols.md
@@ -534,7 +534,7 @@ for thing in things {
## 协议的继承
-协议能够继承一到多个其他协议。语法与类的继承相似,多个协议间用逗号`,`分隔
+协议能够继承一个或多个其他协议,可以在继承的协议基础上增加新的内容要求。协议的继承语法与类的继承相似,多个被继承的协议间用逗号分隔:
```swift
protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
@@ -550,9 +550,9 @@ protocol PrettyTextRepresentable: TextRepresentable {
}
```
-遵循`PrettyTextRepresentable`协议的同时,也需要遵循`TextRepresentable`协议。
+例子中定义了一个新的协议`PrettyTextRepresentable`,它继承自`TextRepresentable`协议。任何遵循`PrettyTextRepresentable`协议的类型在满足该协议的要求时,也必须满足`TextRepresentable`协议的要求。在这个例子中,`PrettyTextRepresentable`协议要求其遵循者提供一个返回值为`String`类型的`asPrettyText`方法。
-如下所示,用`扩展`为`SnakesAndLadders`遵循`PrettyTextRepresentable`协议:
+如下所示,扩展`SnakesAndLadders`,让其遵循`PrettyTextRepresentable`协议:
```swift
extension SnakesAndLadders: PrettyTextRepresentable {
@@ -573,11 +573,11 @@ extension SnakesAndLadders: PrettyTextRepresentable {
}
```
-在`for in`中迭代出了`board`数组中的每一个元素:
+上述扩展使得`SnakesAndLadders`遵循了`PrettyTextRepresentable`协议,并为每个`SnakesAndLadders`类型提供了了协议要求的`asPrettyText()`方法。每个`PrettyTextRepresentable`类型同时也是`TextRepresentable`类型,所以在`asPrettyText`的实现中,可以调用`asText()`方法。之后在每一行加上换行符,作为输出的开始。然后遍历数组中的元素,输出一个几何图形来表示遍历的结果:
-* 当从数组中迭代出的元素的值大于0时,用`▲`表示
-* 当从数组中迭代出的元素的值小于0时,用`▼`表示
-* 当从数组中迭代出的元素的值等于0时,用`○`表示
+* 当从数组中取出的元素的值大于0时,用`▲`表示
+* 当从数组中取出的元素的值小于0时,用`▼`表示
+* 当从数组中取出的元素的值等于0时,用`○`表示
任意`SankesAndLadders`的实例都可以使用`asPrettyText()`方法。
From 595647259c4fcb07c44d530de34c469e42de0464 Mon Sep 17 00:00:00 2001
From: justaway
Date: Sat, 4 Jul 2015 23:32:38 +0800
Subject: [PATCH 077/228] =?UTF-8?q?'25=5FAdvanced=5FOperators'=E7=BF=BB?=
=?UTF-8?q?=E8=AF=91=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
source/chapter2/25_Advanced_Operators.md | 134 ++++++++++++-----------
1 file changed, 68 insertions(+), 66 deletions(-)
diff --git a/source/chapter2/25_Advanced_Operators.md b/source/chapter2/25_Advanced_Operators.md
index b641866b..4d54288a 100644
--- a/source/chapter2/25_Advanced_Operators.md
+++ b/source/chapter2/25_Advanced_Operators.md
@@ -249,73 +249,73 @@ signedOverflow = signedOverflow &- 1
运算符的优先级(`precedence`)使得一些运算符优先于其他运算符,高优先级的运算符会先被计算。
-结合性(`associativity`)定义相同优先级的运算符在一起时是怎么组合或关联的,是和左边的一组呢,还是和右边的一组。意思就是,到底是和左边的表达式结合呢,还是和右边的表达式结合?
+结合性(`associativity`)定义了相同优先级的运算符是如何结合(或关联)的 —— 是与左边结合为一组,还是与右边结合为一组。可以将这意思理解为“它们是与左边的表达式结合的”或者“它们是与右边的表达式结合的”。
-在混合表达式中,运算符的优先级和结合性是非常重要的。举个例子,为什么下列表达式的结果为`4`?
+在复合表达式的运算顺序中,运算符的优先级和结合性是非常重要的。举例来说,为什么下面这个表达式的运算结果是 `4`?
```swift
2 + 3 * 4 % 5
// 结果是 4
```
-如果严格地从左计算到右,计算过程会是这样:
-
+如果严格地从左到右进行运算,则运算的过程是这样的:
- 2 + 3 = 5
- 5 * 4 = 20
-- 20 / 5 = 4 余 0
+- 20 % 5 = 0
-但是正确答案是`4`而不是`0`。优先级高的运算符要先计算,在Swift和C语言中,都是先乘除后加减的。所以,执行完乘法和求余运算才能执行加减运算。
+但是正确答案是 `4` 而不是 `0`。优先级高的运算符要先于优先级低的运算符进行计算。与C语言类似,在 Swift 当中,乘法运算符(`*`)与取余运算符(`%`)的优先级高于加法运算符(`+`)。因此,它们的计算顺序要先于加法运算。
-乘法和求余拥有相同的优先级,在运算过程中,我们还需要结合性,乘法和求余运算都是左结合的。这相当于在表达式中有隐藏的括号让运算从左开始。
+而乘法与取余的优先级相同。这时为了得到正确的运算顺序,还需要考虑结合性。乘法与取余运算都是左结合的。可以将这考虑成为这两部分表达式都隐式地加上了括号:
```swift
2 + ((3 * 4) % 5)
```
-3 * 4 = 12,所以这相当于:
+`(3 * 4) = 12`,所以表达式相当于:
```swift
2 + (12 % 5)
```
-12 % 5 = 2,所这又相当于
+`12 % 5 = 2`,所以表达式相当于:
```swift
2 + 2
```
-计算结果为 4。
+此时可以容易地看出计算的结果为 `4`。
-查阅Swift运算符的优先级和结合性的完整列表,请看[表达式](../chapter3/04_Expressions.html)。
+如果想查看完整的 Swift 运算符优先级和结合性规则,请参考[表达式](../chapter3/04_Expressions.html)。
> 注意:
-Swift的运算符较C语言和Objective-C来得更简单和保守,这意味着跟基于C的语言可能不一样。所以,在移植已有代码到Swift时,注意去确保代码按你想的那样去执行。
+> 对于C语言和 Objective-C 来说,Swift 的运算符优先级和结合性规则是更加简洁和可预测的。但是,这也意味着它们于那些基于C的语言不是完全一致的。在对现有的代码进行移植的时候,要注意确保运算符的行为仍然是按照你所想的那样去执行。
## 运算符函数
-让已有的运算符也可以对自定义的类和结构进行运算,这称为运算符重载。
+类和结构可以为现有的操作符提供自定义的实现,这通常被称为运算符重载(`overloading`)。
-这个例子展示了如何用`+`让一个自定义的结构做加法。算术运算符`+`是一个两目运算符,因为它有两个操作数,而且它必须出现在两个操作数之间。
+下面的例子展示了如何为自定义的结构实现加法操作符(`+`)。算术加法运算符是一个两目运算符(`binary operator`),因为它可以对两个目标进行操作,同时它还是中缀(`infix`)运算符,因为它出现在两个目标中间。
-例子中定义了一个名为`Vector2D`的二维坐标向量 `(x,y)` 的结构,然后定义了让两个`Vector2D`的对象相加的运算符函数。
+例子中定义了一个名为 `Vector2D` 的结构体用来表示二维坐标向量`(x, y)`,紧接着定义了一个可以对两个 `Vector2D` 结构体进行相加的运算符函数(`operator function`):
```swift
struct Vector2D {
var x = 0.0, y = 0.0
}
-@infix func + (left: Vector2D, right: Vector2D) -> Vector2D {
+
+func + (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
```
-该运算符函数定义了一个全局的`+`函数,这个函数需要两个`Vector2D`类型的参数,返回值也是`Vector2D`类型。需要定义和实现一个中置运算的时候,在关键字`func`之前写上属性 `@infix` 就可以了。
+该运算符函数被定义为一个全局函数,并且函数的名字与它要进行重载的 `+` 名字一致。因为算术加法运算符是双目运算符,所以这个运算符函数接收两个类型为 `Vector2D` 的输入参数,同时有一个 `Vector2D` 类型的返回值。
-在这个代码实现中,参数被命名为了`left`和`right`,代表`+`左边和右边的两个`Vector2D`对象。函数返回了一个新的`Vector2D`的对象,这个对象的`x`和`y`分别等于两个参数对象的`x`和`y`的和。
+在这个实现中,输入参数分别被命名为 `left` 和 `right`,代表在 `+` 运算符左边和右边的两个 `Vector2D` 对象。函数返回了一个新的 `Vector2D` 的对象,这个对象的 `x` 和 `y` 分别等于两个参数对象的 `x` 和 `y` 的值之和。
-这个函数是全局的,而不是`Vector2D`结构的成员方法,所以任意两个`Vector2D`对象都可以使用这个中置运算符。
+这个函数被定义成全局的,而不是 `Vector2D` 结构的成员方法,所以任意两个 `Vector2D` 对象都可以使用这个中缀运算符:
```swift
let vector = Vector2D(x: 3.0, y: 1.0)
@@ -324,151 +324,153 @@ let combinedVector = vector + anotherVector
// combinedVector 是一个新的Vector2D, 值为 (5.0, 5.0)
```
-这个例子实现两个向量 `(3.0,1.0)` 和 `(2.0,4.0)` 相加,得到向量 `(5.0,5.0)` 的过程。如下图示:
+这个例子实现两个向量 `(3.0,1.0)` 和 `(2.0,4.0)` 的相加,并得到新的向量 `(5.0,5.0)`。这个过程如下图示:

-### 前置和后置运算符
+### 前缀和后缀运算符
-上个例子演示了一个双目中置运算符的自定义实现,同样我们也可以玩标准单目运算符的实现。单目运算符只有一个操作数,在操作数之前就是前置的,如`-a`; 在操作数之后就是后置的,如`i++`。
+上个例子演示了一个双目中缀运算符的自定义实现。类与结构体也能提供标准单目运算符(`unary operators`)的实现。单目运算符只有一个操作目标。当运算符出现在操作目标之前时,它就是前缀(`prefix`)的(比如 `-a`),而当它出现在操作目标之后时,它就是后缀(`postfix`)的(比如 `i++`)。
-实现一个前置或后置运算符时,在定义该运算符的时候于关键字`func`之前标注 `@prefix` 或 `@postfix` 属性。
+要实现前缀或者后缀运算符,需要在声明运算符函数的时候在 `func` 关键字之前指定 `prefix` 或者 `postfix` 限定符:
```swift
-@prefix func - (vector: Vector2D) -> Vector2D {
+prefix func - (vector: Vector2D) -> Vector2D {
return Vector2D(x: -vector.x, y: -vector.y)
}
```
-这段代码为`Vector2D`类型提供了单目减运算`-a`,`@prefix`属性表明这是个前置运算符。
+这段代码为 `Vector2D` 类型实现了单目减运算符(`-a`)。由于单目减运算符是前缀运算符,所以这个函数需要加上 `prefix` 限定符。
-对于数值,单目减运算符可以把正数变负数,把负数变正数。对于`Vector2D`,单目减运算将其`x`和`y`都进进行单目减运算。
+对于简单数值,单目减运算符可以对它们的正负性进行改变。对于 `Vector2D` 来说,单目减运算将其 `x` 和 `y` 属性的正负性都进行了改变。
```swift
let positive = Vector2D(x: 3.0, y: 4.0)
let negative = -positive
-// negative 为 (-3.0, -4.0)
+// negative 是一个值为 (-3.0, -4.0) 的 Vector2D 实例
+
let alsoPositive = -negative
-// alsoPositive 为 (3.0, 4.0)
+// alsoPositive 是一个值为 (3.0, 4.0) 的 Vector2D 实例
```
-### 组合赋值运算符
+### 复合赋值运算符
-组合赋值是其他运算符和赋值运算符一起执行的运算。如`+=`把加运算和赋值运算组合成一个操作。实现一个组合赋值符号需要使用`@assignment`属性,还需要把运算符的左参数设置成`inout`,因为这个参数会在运算符函数内直接修改它的值。
+复合赋值运算符(`Compound assignment operators`)将赋值运算符(`=`)与其它运算符进行结合。比如,将加法与赋值结合成加法赋值运算符(`+=`)。在实现的时候,需要把运算符的左参数设置成 `inout` 类型,因为这个参数的值会在运算符函数内直接被修改。
```swift
-@assignment func += (inout left: Vector2D, right: Vector2D) {
+func += (inout left: Vector2D, right: Vector2D) {
left = left + right
}
```
-因为加法运算在之前定义过了,这里无需重新定义。所以,加赋运算符函数使用已经存在的高级加法运算符函数来执行左值加右值的运算。
+因为加法运算在之前已经定义过了,所以在这里无需重新定义。在这里可以直接利用现有的加法运算符函数,用它来对左值和右值进行相加,并再次赋值给左值:
```swift
var original = Vector2D(x: 1.0, y: 2.0)
let vectorToAdd = Vector2D(x: 3.0, y: 4.0)
original += vectorToAdd
-// original 现在为 (4.0, 6.0)
+// original 的值现在为 (4.0, 6.0)
```
-你可以将 `@assignment` 属性和 `@prefix` 或 `@postfix` 属性起来组合,实现一个`Vector2D`的前置运算符。
+还可以将赋值与 `prefix` 或 `postfix` 限定符结合起来,下面的代码为 `Vector2D` 实例实现了前缀自增运算符(`++a`):
```swift
-@prefix @assignment func ++ (inout vector: Vector2D) -> Vector2D {
+prefix func ++ (inout vector: Vector2D) -> Vector2D {
vector += Vector2D(x: 1.0, y: 1.0)
return vector
}
```
-这个前置使用了已经定义好的高级加赋运算,将自己加上一个值为 `(1.0,1.0)` 的对象然后赋给自己,然后再将自己返回。
+这个前缀自增运算符使用了前面定义的加法赋值操作。它对 `Vector2D` 的 `x` 和 `y` 属性都进行了加 `1` 操作,再将结果返回:
```swift
var toIncrement = Vector2D(x: 3.0, y: 4.0)
let afterIncrement = ++toIncrement
-// toIncrement 现在是 (4.0, 5.0)
-// afterIncrement 现在也是 (4.0, 5.0)
+// toIncrement 的值现在为 (4.0, 5.0)
+// afterIncrement 的值同样为 (4.0, 5.0)
```
->注意:
-默认的赋值符(=)是不可重载的。只有组合赋值符可以重载。三目条件运算符 `a?b:c` 也是不可重载。
+> 注意:
+> 不能对默认的赋值运算符(`=`)进行重载。只有组合赋值符可以被重载。同样地,也无法对三目条件运算符 `a ? b : c` 进行重载。
-### 比较运算符
+### 等价运算符
-Swift无所知道自定义类型是否相等或不等,因为等于或者不等于由你的代码说了算了。所以自定义的类和结构要使用比较符`==`或`!=`就需要重载。
+自定义的类和结构体没有对等价操作符(`equivalence operators`)进行默认实现,等价操作符通常被称为“相等”操作符(`==`)与“不等”操作符(`!=`)。对于自定义类型,Swift 无法判断其是否“相等”,因为“相等”的含义取决于这些自定义类型在你的代码中所扮演的角色。
-定义相等运算符函数跟定义其他中置运算符雷同:
+为了使用等价操作符来对自定义的类型进行判等操作,需要为其提供自定义实现,实现的方法与其它中缀运算符一样:
```swift
-@infix func == (left: Vector2D, right: Vector2D) -> Bool {
+func == (left: Vector2D, right: Vector2D) -> Bool {
return (left.x == right.x) && (left.y == right.y)
}
-
-@infix func != (left: Vector2D, right: Vector2D) -> Bool {
+func != (left: Vector2D, right: Vector2D) -> Bool {
return !(left == right)
}
```
-上述代码实现了相等运算符`==`来判断两个`Vector2D`对象是否有相等的值,相等的概念就是它们有相同的`x`值和相同的`y`值,我们就用这个逻辑来实现。接着使用`==`的结果实现了不相等运算符`!=`。
+上述代码实现了“相等”运算符(`==`)来判断两个 `Vector2D` 对象是否有相等。对于 `Vector2D` 类型来说,“相等”意味“两个实例的 `x`属性 和 `y` 属性都相等”,这也是代码中用来进行判等的逻辑。示例里同时也实现了“不等”操作符(`!=`),它简单地将“相等”操作符进行取反后返回。
-现在我们可以使用这两个运算符来判断两个`Vector2D`对象是否相等。
+现在我们可以使用这两个运算符来判断两个 `Vector2D` 对象是否相等。
```swift
let twoThree = Vector2D(x: 2.0, y: 3.0)
let anotherTwoThree = Vector2D(x: 2.0, y: 3.0)
if twoThree == anotherTwoThree {
- println("这两个向量是相等的.")
+ print("These two vectors are equivalent.")
}
-// prints "这两个向量是相等的."
+// prints "These two vectors are equivalent."
```
### 自定义运算符
-标准的运算符不够玩,那你可以声明一些个性的运算符,但个性的运算符只能使用这些字符 `/ = - + * % < > ! & | ^ . ~`。
+除了实现标准运算符,在 Swift 当中还可以声明和实现自定义运算符(`custom operators`)。可以用来自定义运算符的字符列表请参考[操作符](../chapter3/02_Lexical_Structure.html#operators)
-新的运算符声明需在全局域使用`operator`关键字声明,可以声明为前置,中置或后置的。
+新的运算符要在全局作用域内,使用 `operator` 关键字进行声明,同时还要指定 `prefix`、`infix` 或者 `postfix` 限定符:
```swift
operator prefix +++ {}
```
-
-这段代码定义了一个新的前置运算符叫`+++`,此前Swift并不存在这个运算符。此处为了演示,我们让`+++`对`Vector2D`对象的操作定义为 `双自增` 这样一个独有的操作,这个操作使用了之前定义的加赋运算实现了自已加上自己然后返回的运算。
+上面的代码定义了一个新的名为 `+++` 的前缀运算符。对于这个运算符,在 Swift 中并没有意义,因为我们针对 `Vector2D` 的实例来定义它的意义。对这个示例来讲,`+++` 被实现为“前缀双自增”运算符。它使用了前面定义的复合加法操作符来让矩阵对自身进行相加,从而让 `Vector2D` 实例的 `x` 属性和 `y`属性的值翻倍:
```swift
-@prefix @assignment func +++ (inout vector: Vector2D) -> Vector2D {
+prefix func +++ (inout vector: Vector2D) -> Vector2D {
vector += vector
return vector
}
```
-`Vector2D` 的 `+++` 的实现和 `++` 的实现很接近, 唯一不同的是前者是加自己, 后者是加值为 `(1.0, 1.0)` 的向量.
+`Vector2D` 的 `+++` 的实现和 `++` 的实现很相似, 唯一不同的是前者对自身进行相加, 而后者是与另一个值为 `(1.0, 1.0)` 的向量相加.
```swift
var toBeDoubled = Vector2D(x: 1.0, y: 4.0)
let afterDoubling = +++toBeDoubled
-// toBeDoubled 现在是 (2.0, 8.0)
-// afterDoubling 现在也是 (2.0, 8.0)
+// toBeDoubled 现在的值为 (2.0, 8.0)
+// afterDoubling 现在的值也为 (2.0, 8.0)
```
-### 自定义中置运算符的优先级和结合性
+### 自定义中缀运算符的优先级和结合性
-可以为自定义的中置运算符指定优先级和结合性。可以回头看看[优先级和结合性](#PrecedenceandAssociativity)解释这两个因素是如何影响多种中置运算符混合的表达式的计算的。
+自定义的中缀(`infix`)运算符也可以指定优先级(`precedence`)和结合性(`associativity`)。[优先级和结合性](#PrecedenceandAssociativity)中详细阐述了这两个特性是如何对中缀运算符的运算产生影响的。
-结合性(associativity)的值可取的值有`left`,`right`和`none`。左结合运算符跟其他优先级相同的左结合运算符写在一起时,会跟左边的操作数结合。同理,右结合运算符会跟右边的操作数结合。而非结合运算符不能跟其他相同优先级的运算符写在一起。
+结合性(`associativity`)可取的值有` left`,`right` 和 `none`。当左结合运算符跟其他相同优先级的左结合运算符写在一起时,会跟左边的操作数进行结合。同理,当右结合运算符跟其他相同优先级的右结合运算符写在一起时,会跟右边的操作数进行结合。而非结合运算符不能跟其他相同优先级的运算符写在一起。
-结合性(associativity)的值默认为`none`,优先级(precedence)默认为`100`。
+结合性(`associativity`)的默认值是 `none`,优先级(`precedence`)如果没有指定,则默认为 `100`。
-以下例子定义了一个新的中置符`+-`,是左结合的`left`,优先级为`140`。
+以下例子定义了一个新的中缀运算符 `+-`,此操作符是左结合的,并且它的优先级为 `140`:
```swift
-operator infix +- { associativity left precedence 140 }
+infix operator +- { associativity left precedence 140 }
func +- (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y - right.y)
}
let firstVector = Vector2D(x: 1.0, y: 2.0)
let secondVector = Vector2D(x: 3.0, y: 4.0)
let plusMinusVector = firstVector +- secondVector
-// plusMinusVector 此时的值为 (4.0, -2.0)
+// plusMinusVector 是一个 Vector2D 类型,并且它的值为 (4.0, -2.0)
```
-这个运算符把两个向量的`x`相加,把向量的`y`相减。因为他实际是属于加减运算,所以让它保持了和加法一样的结合性和优先级(`left`和`140`)。查阅完整的Swift默认结合性和优先级的设置,请移步[表达式](../chapter3/04_Expressions.html);
+这个运算符把两个向量的 `x` 值相加,同时用第一个向量的 `y` 值减去第二个向量的 `y` 值。因为它本质上是属于“加型”运算符,所以将它的结合性和优先级被设置为(`left` 和 `140`),这与 `+` 和 `-` 等默认的中缀加型操作符是相同的。完整的 Swift 操作符默认结合性与优先级请参考[表达式](../chapter3/04_Expressions.html)。
+
+> 注意:
+> 当定义前缀与后缀操作符的时候,我们并没有指定优先级。然而,如果对同一个操作数同时使用前缀与后缀操作符,则后缀操作符会先被执行。
From 1b0ec3b5d9b4660568fe6498513d8a8d44281e9d Mon Sep 17 00:00:00 2001
From: littledogboy
Date: Sun, 5 Jul 2015 10:35:26 +0800
Subject: [PATCH 078/228] =?UTF-8?q?statements=E7=BF=BB=E8=AF=91=E4=BA=8C?=
=?UTF-8?q?=E4=BB=A3=E7=9B=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
添加了跳转。使部分语句变得更通顺。
---
source/chapter3/10_Statements.md | 97 +++++++++++++++++++-------------
1 file changed, 59 insertions(+), 38 deletions(-)
diff --git a/source/chapter3/10_Statements.md b/source/chapter3/10_Statements.md
index 7a98a9b1..c122756a 100755
--- a/source/chapter3/10_Statements.md
+++ b/source/chapter3/10_Statements.md
@@ -1,6 +1,7 @@
> 翻译:[coverxit](https://github.com/coverxit),[littledogboy](https://github.com/littledogboy)
> 校对:[numbbbbb](https://github.com/numbbbbb), [coverxit](https://github.com/coverxit), [stanzhai](https://github.com/stanzhai),[littledogboy](https://github.com/littledogboy)
-
+
+
# 语句
-----------------
@@ -39,7 +40,8 @@
> *循环语句* → [*for-in语句*](..\chapter3\10_Statements.html#for_in_statement)
> *循环语句* → [*while语句*](..\chapter3\10_Statements.html#wheetatype类型ile_statement)
> *循环语句* → [*do-while语句*](..\chapter3\10_Statements.html#do_while_statement)
-
+
+
### For 语句
`for`语句只有在循环条件为真时重复执行代码块,此时计数器递增。
@@ -65,7 +67,9 @@
> *for语句* → **for** [*for初始条件*](..\chapter3\10_Statements.html#for_init) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block)
> *for语句* → **for** **(** [*for初始条件*](..\chapter3\10_Statements.html#for_init) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ **)** [*代码块*](..\chapter3\05_Declarations.html#code_block)
> *for初始条件* → [*变量声明*](..\chapter3\05_Declarations.html#variable_declaration) | [*表达式列表*](..\chapter3\04_Expressions.html#expression_list)
-
+
+
+
### For-In 语句
`for-in`语句允许在重复执行代码块的同时,迭代集合(或遵循`Sequence`协议的任意类型)中的每一项。
@@ -80,7 +84,9 @@
> For-In 循环语法
> *for-in语句* → **for** [*模式*](..\chapter3\07_Patterns.html#pattern) **in** [*表达式*](..\chapter3\04_Expressions.html#expression) [*代码块*](..\chapter3\05_Declarations.html#code_block)
-
+
+
+
### While 语句
`while`语句当循环条件为真时,允许重复执行代码块。
@@ -103,11 +109,21 @@
> While 循环语法
> *while语句* → **while** [*while条件*](..\chapter3\10_Statements.html#while_condition) [*代码块*](..\chapter3\05_Declarations.html#code_block)
-> *while条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*声明*](..\chapter3\05_Declarations.html#declaration)
-> *表达式* → [*表达式*](..\chapter3\04_Expressions.html#expression)
-> *表达式* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [条件列表](TODO)
-> *表达式* →
-
+> *条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*声明*](..\chapter3\05_Declarations.html#declaration)
+> *条件* → [*表达式*](..\chapter3\04_Expressions.html#expression)
+> *条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*条件列表*](TODO)
+> *条件* → [*可用条件*](..\chapter3\10_Statement.html#availability) [*表达式*](..\chapter3\04_Expressions.html#expression)
+> *条件列表* → [*条件条件*](TODO) [*条件列表*](TODO)
+> *条件* → [*可用条件*](..\chapter3\10_Statement.html#availability) [可选绑定条件](../chapter2/01_The_Basics.html#optional_binding)
+> *case条件* → **case** [*模式*](..\chapter3\07_Patterns.html#pattern) [构造器](TODO) [where](DOTO)
+> *可选绑定条件* → [可选绑定头](TODO) [持续可选绑定](TODO) [持续可选绑定列表](TODO)
+> *可选绑定头* → **let** [*模式*](..\chapter3\07_Patterns.html#pattern) [构造器](TODO) **var** [*模式*](..\chapter3\07_Patterns.html#pattern) [构造器](TODO)
+> *可持续绑定列表* → [*模式*](..\chapter3\07_Patterns.html#pattern) | [构造器](TODO) [可选绑定头](TODO)
+>
+
+
+
+
### Repeat-While 语句
`repeat-while`语句允许代码块被执行一次或多次。
@@ -141,7 +157,9 @@
> 分支语句语法
> *分支语句* → [*if语句*](..\chapter3\10_Statements.html#if_statement)
> *分支语句* → [*switch语句*](..\chapter3\10_Statements.html#switch_statement)
-
+
+
+
### If 语句
取决于一个或多个条件的值,`if`语句将决定执行哪一块代码。
@@ -176,21 +194,23 @@
`if`语句中条件的值的类型必须遵循`LogicValue`协议。同时,条件也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
> If语句语法
-> *if语句* → **if** [*if条件*](..\chapter3\10_Statements.html#if_condition) [*代码块*](..\chapter3\05_Declarations.html#code_block) [*else子句(Clause)*](..\chapter3\10_Statements.html#else_clause) _可选_
+> *if语句* → **if** [*if条件*](..\chapter3\10_Statements.html#if_condition) [*代码块*](..\chapter3\05_Declarations.html#code_block) [*else(Clause)*](..\chapter3\10_Statements.html#else_clause) _可选_
> *if条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*声明*](..\chapter3\05_Declarations.html#declaration)
-> *else子句(Clause)* → **else** [*代码块*](..\chapter3\05_Declarations.html#code_block) | **else** [*if语句*](..\chapter3\10_Statements.html#if_statement)
+> *else(Clause)* → **else** [*代码块*](..\chapter3\05_Declarations.html#code_block) | **else** [*if语句*](..\chapter3\10_Statements.html#if_statement)
+
+
### Guard 语句
-`guard` 语句用来转移程序控制出该作用域,假如一个或者多个多个条件不成立。
+`guard` 语句用来转移程序控制出其作用域,如果一个或者多个条件不成立。
`guard` 语句的格式如下:
> guard `condition` else {
`statements`
>}
- `guard`语句中条件的值的类型必须遵循`LogicValue`协议。同时,条件也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
+ `guard`语句中条件值的类型必须遵循`LogicValue`协议。且条件可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。
- 在`guard`语句中声明的常量或者变量,可使用范围为从声明开始到作用域结束,常量和变量的值从可选绑定声明中分配。
+ 在`guard`语句中声明的常量或者变量,可用范围从声明开始到作用域结束,常量和变量的值从可选绑定声明中分配。
`guard`语句需要有`else`子句,并且必须调用被`noreturn`属性标记的函数,或者使用下面的语句把程序执行转移到guard语句的作用域外。
@@ -199,8 +219,10 @@
* `continue`
* `throw`
-执行转移语句详情参见[执行转移语句](TODO)
-
+执行转移语句详情参见[控制传递语句](TODO)
+
+
+
### Switch 语句
取决于`switch`语句的*控制表达式(control expression)*,`switch`语句将决定执行哪一块代码。
@@ -251,12 +273,11 @@ case let (x, y) where x == y:
> *case标签* → **case** [*case项列表*](..\chapter3\10_Statements.html#case_item_list) **:**
> *case项列表* → [*模式*](..\chapter3\07_Patterns.html#pattern) [*guard-clause*](..\chapter3\10_Statements.html#guard_clause) _可选_ | [*模式*](..\chapter3\07_Patterns.html#pattern) [*guard-clause*](..\chapter3\10_Statements.html#guard_clause) _可选_ **,** [*case项列表*](..\chapter3\10_Statements.html#case_item_list)
> *default标签* → **default** **:**
-> *where-clause* → **where** [*guard-expression*](..\chapter3\10_Statements.html#guard_expression)
+> *where-clause* → **where** [*guard-expression*](..\chapter3\10_Statements.html#guard)
> *where-expression* → [*表达式*](..\chapter3\04_Expressions.html#expression)
-
+
-
## 带标签的语句
你可以在循环语句或`switch`语句前面加上*标签*,它由标签名和紧随其后的冒号(:)组成。在`break`和`continue`后面跟上标签名可以显式地在循环语句或`switch`语句中更改控制流,把控制权传递给指定标签标记的语句。关于这两条语句用法,详情参见 [Break 语句](#break_statement)和 [Continue 语句](#continue_statement)。
@@ -270,7 +291,7 @@ case let (x, y) where x == y:
> *语句标签* → [*标签名称*](..\chapter3\10_Statements.html#label_name) **:**
> *标签名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
-
+
## 控制传递语句
通过无条件地把控制权从一片代码传递到另一片代码,控制传递语句能够改变代码执行的顺序。Swift 提供四种类型的控制传递语句:`break`语句、`continue`语句、`fallthrough`语句和`return`语句。
@@ -282,7 +303,7 @@ case let (x, y) where x == y:
> *控制传递语句* → [*return语句*](..\chapter3\10_Statements.html#return_statement)
> *控制传递语句* → [*throw语句*](..\chapter3\10_Statements.html#throw_statement)
-
+
### Break 语句
`break`语句用于终止循环或`switch`语句的执行。使用`break`语句时,可以只写`break`这个关键词,也可以在`break`后面跟上标签名(label name),像下面这样:
@@ -301,7 +322,7 @@ case let (x, y) where x == y:
> Break 语句语法
> *break语句* → **break** [*标签名称*](..\chapter3\10_Statements.html#label_name) _可选_
-
+
### Continue 语句
`continue`语句用于终止循环中当前迭代的执行,但不会终止该循环的执行。使用`continue`语句时,可以只写`continue`这个关键词,也可以在`continue`后面跟上标签名(label name),像下面这样:
@@ -322,7 +343,7 @@ case let (x, y) where x == y:
> Continue 语句语法
> *continue语句* → **continue** [*标签名称*](..\chapter3\10_Statements.html#label_name) _可选_
-
+
### Fallthrough 语句
`fallthrough`语句用于在`switch`语句中传递控制权。`fallthrough`语句会把控制权从`switch`语句中的一个 case 传递给下一个 case 。这种传递是无条件的,即使下一个 case 的模式与`switch`语句的控制表达式的值不匹配。
@@ -334,7 +355,7 @@ case let (x, y) where x == y:
> Fallthrough 语句语法
> *fallthrough语句* → **fallthrough**
-
+
### Return 语句
`return`语句用于在函数或方法的实现中将控制权传递给调用者,接着程序将会从调用者的位置继续向下执行。
@@ -351,7 +372,7 @@ case let (x, y) where x == y:
> Return 语句语法
> *return语句* → **return** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_
-
+
### Availability 语句
可用性条件,被当做`if` ,`while` 语句的条件,并且 `guard` 语句在运行时会基于特定的语法格式查询接口的可用性。
@@ -363,10 +384,10 @@ avaliability 语句的形式如下:
> `fallback statements to execute if the APIs are unavailable`
> }
-可用性条件执行一个代码块时,取决于在运行时你想要使用的接口是否可用。
+可用性条件执行一个代码块时,取决于在运行时想要使用的接口是否可用。
当编译器检查到代码块中的接口是可用的,则从可用性条件中获取相应信息。
-可用性条件使用逗号分隔平台名称和版本列表。使用`iOS`,`OSX`,以及`watchOS`为平台名称,包括相应的版本号。*参数是必需的。在任何平台上代码块主体都被可用性条件保护起来,由目标规定的最小部署目标执行。
+可用性条件使用逗号分隔平台名称和版本列表。使用`iOS`,`OSX`,以及`watchOS`为平台名称,包括相应的版本号。*参数是必需的。在任何平台上代码块主体都被可用性条件保护起来,由满足最低部署条件的目标设备运行。
与布尔类型条件不同,不能用逻辑运算符 **&&** 和 **||** 合并可用性条件。
@@ -383,7 +404,7 @@ avaliability 语句的形式如下:
> *版本号* → [十进制数字](TODO) **.** [十进制数字](TODO) **.** [十进制数字](TODO)
-
+
### Throw 语句
`throw`语句出现在抛出函数或者抛出方法体内,或者类型被`throws`关键字标记的表达式体内。
@@ -400,14 +421,14 @@ avaliability 语句的形式如下:
> throw 语句语法
> *抛出语句* → **throw** *[表达式](TODO)*
-
+
### Defer 语句
`defer` 语句用于转移程序控制出延迟语句作用域之前执行代码。
在 `defer` 语句中的语句无论程序控制如何转移都会执行。这意味着 `defer` 语句可以被使用在以下这些情况,像手动得执行资源管理,关闭文件描述,或者即使抛出了错误也需要去实现执行一些动作。
-如果多个 `defer` 语句出现在同一范围内,那么它们执行的顺序与它们出现的顺序相反。最后执行的 `defer` 语句为给定范围内的第一个,这意味着最后的延迟语句中的语句涉及的资源可以被其他 `defer`语句清理掉。
+如果多个 `defer` 语句出现在同一范围内,那么它们执行的顺序与出现的顺序相反。给定作用域中的第一个`defer` 语句,会在最后执行,这意味着最后执行的延迟语句中的语句涉及的资源可以被其他 `defer`语句清理掉。
> 1 func f( ) {
> 2 defer { print("First") }
@@ -420,13 +441,13 @@ avaliability 语句的形式如下:
> 9 // prints "First"
-`defer` 语句中的语句无法转移程序控制权出延迟语句。
+`defer` 语句中的语句无法转移程序控制出延迟语句。
> defer 语句语法
> *延迟语句* → **defer** *[代码块](TODO)*
-
+
### Do 语句
`do` 语句用于引入一个新的作用域,该作用域中可以含有一个或多个`catch`子句,catch子句中定义了一些匹配错误情况的模式。`do` 语句作用域内定义的常量和变量,只能在do语句作用域内访问。
@@ -441,17 +462,17 @@ avaliability 语句的形式如下:
> }
-如同`switch`语句,编译器会判断`catch`子句是否被遗漏。如果这样的决定被执行,则视为错误被处理。否则,错误会自动传播出包含作用域,被一个封闭的`catch`语句或抛出函数处理,包含函数必须以`throws`关键字声明。
+如同`switch`语句,编译器会判断`catch`子句是否被遗漏。如果catch没有被遗漏,则认为错误被处理。否则,错误会自动传播出包含作用域,被一个封闭的`catch`语句或抛出函数处理掉,包含函数必须以`throws`关键字声明。
-为了确保错误已经被处理,使用一个匹配所有错误的`catch`子句,如通配符模式(_)。如果一个`catch`子句不指定一种模式,catch子句会匹配和结合任何错误本地命名常量错误。有关可在catch子句中使用了图纹的更多信息,请参阅模式。
+
为了确保错误已经被处理,使用一个匹配所有错误的`catch`子句,如通配符模式(_)。如果一个`catch`子句不指定一种模式,`catch`子句会匹配和约束任何局部变量命名的`error`。有关在`catch`子句中使用模式的更多信息,详见[模式](TODO)。
关于在一些`catch`子句中如何使用` do`语句的例子,详情参见[错误处理](TODO)一章的[抛出错误](TODO)。
-> do 语句语法 → **do** *[代码块](TODO) [catch子句](TODO)*
-> catch子句 → *[catch子句](TODO) [catch子句](TODO)*
-> catch子句 → **catch** **[模式](TODO)** *可选的* [where子句]() *可选的* [代码块](TODO)
+> do 语句语法 → **do** *[*代码块*](..\chapter3\05_Declarations.html#code_block) [catch](TODO)*
+> catch → *[catch子句](TODO) [catch子句](TODO)*
+> catch → **catch** *[*模式*](..\chapter3\07_Patterns.html#pattern)** *可选的* [*where*]() *可选的* [*代码块*](..\chapter3\05_Declarations.html#code_block)
From f0cf0960da31fe2675511e425d3cba45df2575c1 Mon Sep 17 00:00:00 2001
From: miaosiqi <1336225019@qq.com>
Date: Sun, 5 Jul 2015 10:49:02 +0800
Subject: [PATCH 079/228] Update 09_Summary_of_the_Grammar.md
---
source/chapter3/09_Summary_of_the_Grammar.md | 561 +++++++++++++------
1 file changed, 380 insertions(+), 181 deletions(-)
diff --git a/source/chapter3/09_Summary_of_the_Grammar.md b/source/chapter3/09_Summary_of_the_Grammar.md
index 2e307e09..f6440c63 100755
--- a/source/chapter3/09_Summary_of_the_Grammar.md
+++ b/source/chapter3/09_Summary_of_the_Grammar.md
@@ -1,5 +1,5 @@
> 翻译:[stanzhai](https://github.com/stanzhai)
-> 校对:[xielingwang](https://github.com/xielingwang)
+> 校对:[xielingwang](https://github.com/xielingwang), [miaosiqi](https://github.com/miaosiqi)
# 语法总结
_________________
@@ -10,7 +10,7 @@ _________________
* [泛型参数(Generic Parameters and Arguments)](#generic_parameters_and_arguments)
* [声明(Declarations)](#declarations)
* [模式(Patterns)](#patterns)
-* [特性(Attributes)](#attributes)
+* [属性(Attributes)](#attributes)
* [表达式(Expressions)](#expressions)
* [词法结构(Lexical Structure)](#lexical_structure)
* [类型(Types)](#types)
@@ -25,6 +25,10 @@ _________________
> *语句* → [*分支语句*](..\chapter3\10_Statements.html#branch_statement) **;** _可选_
> *语句* → [*标记语句(Labeled Statement)*](..\chapter3\10_Statements.html#labeled_statement)
> *语句* → [*控制转移语句*](..\chapter3\10_Statements.html#control_transfer_statement) **;** _可选_
+> *语句* → [*延迟语句*](TODO) **;** _可选_
+
+> *语句* → [*执行语句*](TODO) **;** _可选_
+
> *多条语句(Statements)* → [*语句*](..\chapter3\10_Statements.html#statement) [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements) _可选_
@@ -33,61 +37,89 @@ _________________
> *循环语句* → [*for语句*](..\chapter3\10_Statements.html#for_statement)
> *循环语句* → [*for-in语句*](..\chapter3\10_Statements.html#for_in_statement)
> *循环语句* → [*while语句*](..\chapter3\10_Statements.html#wheetatype类型ile_statement)
-> *循环语句* → [*do-while语句*](..\chapter3\10_Statements.html#do_while_statement)
+> *循环语句* → [*repeat-while语句*](..\chapter3\10_Statements.html#do_while_statement)
> For 循环语法
> *for语句* → **for** [*for初始条件*](..\chapter3\10_Statements.html#for_init) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block)
> *for语句* → **for** **(** [*for初始条件*](..\chapter3\10_Statements.html#for_init) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ **;** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_ **)** [*代码块*](..\chapter3\05_Declarations.html#code_block)
-> *for初始条件* → [*变量声明*](..\chapter3\05_Declarations.html#variable_declaration) | [*表达式列表*](..\chapter3\04_Expressions.html#expression_list)
+> *for初始条件* → [*变量声明*](..\chapter3\05_Declarations.html#variable_declaration) | [*表达式集*](..\chapter3\04_Expressions.html#expression_list)
> For-In 循环语法
-> *for-in语句* → **for** [*模式*](..\chapter3\07_Patterns.html#pattern) **in** [*表达式*](..\chapter3\04_Expressions.html#expression) [*代码块*](..\chapter3\05_Declarations.html#code_block)
+> *for-in语句* → **for case** _可选_ [*模式*](..\chapter3\07_Patterns.html#pattern) **in** [*表达式*](..\chapter3\04_Expressions.html#expression) [*代码块*](..\chapter3\05_Declarations.html#code_block) [*where从句*](TODO) _可选_
> While 循环语法
-> *while语句* → **while** [*while条件*](..\chapter3\10_Statements.html#while_condition) [*代码块*](..\chapter3\05_Declarations.html#code_block)
-> *while条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*声明*](..\chapter3\05_Declarations.html#declaration)
+> *while语句* → **while** [*条件从句*](..\chapter3\10_Statements.html#while_condition) [*代码块*](..\chapter3\05_Declarations.html#code_block)
+> *条件从句* → [*表达式*](TODO)
+
+> *条件从句* → [*表达式*](TODO) *,* [*表达式集*]()
+
+>*条件从句* → [*表达式集*](TODO)
+
+> *条件从句* → [*可用条件 (availability-condition*)](TODO) *|* [*表达式集*]()
+
+> *条件集* → [*条件*](TODO) *|* [*条件*](TODO) *,* [*条件集*]()
+
+> *条件* → [*可用条件(availability-condition)*](TODO) *|* [*个例条件(case-condition)*](TODO) *|* [*可选绑定条件(optional-binding-condition)*](TODO)
+
+> *个例条件(case-condition)* → **case** [*模式*](TODO) [*构造器*](TODO) [*where从句*](TODO)_可选_
+
+> *可选绑定条件(optional-binding-condition)* → [*可选绑定头(optional-binding-head)*](TODO) [*可选绑定连续集(optional-binding-continuation-list)*](TODO) _可选_ [*where从句*](TODO) _可选_
+
+> *可选绑定头(optional-binding-head)* → **let** [*模式 构造器*](TODO) *|* **var** [*模式 构造器*](TODO)
+
+> *可选绑定连续集(optional-binding-contiuation-list)* → [*可选绑定连续(optional-binding-contiuation)*](TODO) *|* [*可选绑定连续(optional-binding-contiuation)*](TODO) *,* [*可选绑定连续集(optional-binding-contiuation-list)*](TODO)
+
+> *可选绑定连续(optional-binding-continuation)* → [*模式 构造器*](TODO) *|* [*可选绑定头(optional-binding-head)*](TODO)
-
-> Do-While 循环语法
-> *do-while语句* → **do** [*代码块*](..\chapter3\05_Declarations.html#code_block) **while** [*while条件*](..\chapter3\10_Statements.html#while_condition)
+> Repeat-While语句语法
+*repeat-while-statement* → **repeat** [*代码块*](TODO) **while** [*表达式*](TODO)
> 分支语句语法
-> *分支语句* → [*if语句*](..\chapter3\10_Statements.html#if_statement)
+> *分支语句* → [*if语句*](..\chapter3\10_Statements.html#if_statement)
+
+> *分支语句* → [*guard语句*](TODO)
+
> *分支语句* → [*switch语句*](..\chapter3\10_Statements.html#switch_statement)
> If语句语法
-> *if语句* → **if** [*if条件*](..\chapter3\10_Statements.html#if_condition) [*代码块*](..\chapter3\05_Declarations.html#code_block) [*else子句(Clause)*](..\chapter3\10_Statements.html#else_clause) _可选_
-> *if条件* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*声明*](..\chapter3\05_Declarations.html#declaration)
-> *else子句(Clause)* → **else** [*代码块*](..\chapter3\05_Declarations.html#code_block) | **else** [*if语句*](..\chapter3\10_Statements.html#if_statement)
+> *if语句* → **if** [*条件从句*](TODO) [*代码块*](TODO) [*else从句(Clause)*](TODO) _可选_
+
+> *else从句(Clause)* → **else** [*代码块*](..\chapter3\05_Declarations.html#code_block) | **else** [*if语句*](..\chapter3\10_Statements.html#if_statement)
+
+
+>Guard 语句语法
+>*guard语句* → **guard** [*条件从句*](TODO) **else** [*代码块*](TODO)
+
+
> Switch语句语法
-> *switch语句* → **switch** [*表达式*](..\chapter3\04_Expressions.html#expression) **{** [*SwitchCase列表*](..\chapter3\10_Statements.html#switch_cases) _可选_ **}**
-> *SwitchCase列表* → [*SwitchCase*](..\chapter3\10_Statements.html#switch_case) [*SwitchCase列表*](..\chapter3\10_Statements.html#switch_cases) _可选_
+> *switch语句* → **switch** [*表达式*](..\chapter3\04_Expressions.html#expression) **{** [*SwitchCase*](..\chapter3\10_Statements.html#switch_cases) _可选_ **}**
+> *SwitchCase集* → [*SwitchCase*](..\chapter3\10_Statements.html#switch_case) [*SwitchCase集*](..\chapter3\10_Statements.html#switch_cases) _可选_
> *SwitchCase* → [*case标签*](..\chapter3\10_Statements.html#case_label) [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements) | [*default标签*](..\chapter3\10_Statements.html#default_label) [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements)
> *SwitchCase* → [*case标签*](..\chapter3\10_Statements.html#case_label) **;** | [*default标签*](..\chapter3\10_Statements.html#default_label) **;**
-> *case标签* → **case** [*case项列表*](..\chapter3\10_Statements.html#case_item_list) **:**
-> *case项列表* → [*模式*](..\chapter3\07_Patterns.html#pattern) [*guard-clause*](..\chapter3\10_Statements.html#guard_clause) _可选_ | [*模式*](..\chapter3\07_Patterns.html#pattern) [*guard-clause*](..\chapter3\10_Statements.html#guard_clause) _可选_ **,** [*case项列表*](..\chapter3\10_Statements.html#case_item_list)
+> *case标签* → **case** [*case项集*](..\chapter3\10_Statements.html#case_item_list) **:**
+> *case项集* → [*模式*](..\chapter3\07_Patterns.html#pattern) [*where-clause*](..\chapter3\10_Statements.html#guard_clause) _可选_ | [*模式*](..\chapter3\07_Patterns.html#pattern) [*where-clause*](..\chapter3\10_Statements.html#guard_clause) _可选_ **,** [*case项集*](..\chapter3\10_Statements.html#case_item_list)
> *default标签* → **default** **:**
-> *guard-clause* → **where** [*guard-expression*](..\chapter3\10_Statements.html#guard_expression)
-> *guard-expression* → [*表达式*](..\chapter3\04_Expressions.html#expression)
+> *where从句* → **where** [*where表达式*](TODO)
+> *where表达式* → [*表达式*](TODO)
> 标记语句语法
-> *标记语句(Labeled Statement)* → [*语句标签*](..\chapter3\10_Statements.html#statement_label) [*循环语句*](..\chapter3\10_Statements.html#loop_statement) | [*语句标签*](..\chapter3\10_Statements.html#statement_label) [*switch语句*](..\chapter3\10_Statements.html#switch_statement)
+> *标记语句(Labeled Statement)* → [*语句标签*](..\chapter3\10_Statements.html#statement_label) [*循环语句*](..\chapter3\10_Statements.html#loop_statement) | [*语句标签*](..\chapter3\10_Statements.html#statement_label) [*if语句*](..\chapter3\10_Statements.html#switch_statement) | [*语句标签*](TODY) [*switch语句*](TODY)
> *语句标签* → [*标签名称*](..\chapter3\10_Statements.html#label_name) **:**
> *标签名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
@@ -97,7 +129,8 @@ _________________
> *控制传递语句* → [*break语句*](..\chapter3\10_Statements.html#break_statement)
> *控制传递语句* → [*continue语句*](..\chapter3\10_Statements.html#continue_statement)
> *控制传递语句* → [*fallthrough语句*](..\chapter3\10_Statements.html#fallthrough_statement)
-> *控制传递语句* → [*return语句*](..\chapter3\10_Statements.html#return_statement)
+> *控制传递语句* → [*return语句*](..\chapter3\10_Statements.html#return_statement)
+> *控制传递语句* → [*throw语句*](TODO)
@@ -119,27 +152,71 @@ _________________
> Return 语句语法
> *return语句* → **return** [*表达式*](..\chapter3\04_Expressions.html#expression) _可选_
+
+>可用条件(Availability Condition)语法
+
+>*可用条件(availability-condition)* → **#available** **(** [*多可用参数*(availability-arguments)](TODO) **)**
+
+>*多可用参数(availability- arguments)* → [*可用参数(availability-argument)*](TODO)|[*可用参数(availability-argument)*](TODO) , [多可用参数(availability-arguments)](TODO)
+
+>*可用参数(availability- argument)* → [*平台名(platform-name)*](TODO) [*平台版本(platform-version)*](TODO)
+
+>*可用参数(availability- argument)* → *
+
+>*平台名* → **iOS** | **iOSApplicationExtension**
+
+>*平台名* → **OSX** | **OSXApplicationExtension**
+
+>*平台名* → **watchOS**
+
+>*平台版本* → [*十进制数(decimal-digits)*](TODO)
+
+>*平台版本* → [*十进制数(decimal-digits)*](TODO) . [*十进制数(decimal-digits)*](TODO)
+
+>*平台版本* → [*十进制数(decimal-digits)*](TODO) **.** [*十进制数(decimal-digits)*](TODO) **.** [*十进制数(decimal-digits)*](TODO))
+
+
+>抛出语句(Throw Statement)语法
+
+>*抛出语句(throw-statement)* → **throw** [*表达式(expression)*](TODO)
+
+
+>延迟语句 (defer-statement)语法
+
+>*延迟语句(defer-statement)* → **defer** [*代码块*](TODO)
+
+
+>执行语句(do-statement)语法
+
+>*执行语句(do-statement)* → **do** [*代码块*](TODO) [*catch-clauses*](TODO) _可选_
+
+>*catch-clauses* → [*catch-clause*](TODO) [*catch-clauses*](TODO) _可选_
+
+>*catch-clauses* → **catch** [*模式(pattern)*](TODO) _可选_ [*where-clause*](TODO) _可选_ [*代码块(code-block)*](TODO) _可选_
+
+
+
## 泛型参数
-> 泛型形参子句(Generic Parameter Clause) 语法
-> *泛型参数子句* → **<** [*泛型参数列表*](GenericParametersAndArguments.html#generic_parameter_list) [*约束子句*](GenericParametersAndArguments.html#requirement_clause) _可选_ **>**
-> *泛型参数列表* → [*泛形参数*](GenericParametersAndArguments.html#generic_parameter) | [*泛形参数*](GenericParametersAndArguments.html#generic_parameter) **,** [*泛型参数列表*](GenericParametersAndArguments.html#generic_parameter_list)
+> 泛型形参从句(Generic Parameter Clause) 语法
+> *泛型参数从句* → **<** [*泛型参数集*](GenericParametersAndArguments.html#generic_parameter_list) [*约束从句*](GenericParametersAndArguments.html#requirement_clause) _可选_ **>**
+> *泛型参数集* → [*泛形参数*](GenericParametersAndArguments.html#generic_parameter) | [*泛形参数*](GenericParametersAndArguments.html#generic_parameter) **,** [*泛型参数集*](GenericParametersAndArguments.html#generic_parameter_list)
> *泛形参数* → [*类型名称*](..\chapter3\03_Types.html#type_name)
> *泛形参数* → [*类型名称*](..\chapter3\03_Types.html#type_name) **:** [*类型标识*](..\chapter3\03_Types.html#type_identifier)
> *泛形参数* → [*类型名称*](..\chapter3\03_Types.html#type_name) **:** [*协议合成类型*](..\chapter3\03_Types.html#protocol_composition_type)
-> *约束子句* → **where** [*约束列表*](GenericParametersAndArguments.html#requirement_list)
-> *约束列表* → [*约束*](GenericParametersAndArguments.html#requirement) | [*约束*](GenericParametersAndArguments.html#requirement) **,** [*约束列表*](GenericParametersAndArguments.html#requirement_list)
+> *约束从句* → **where** [*约束集*](GenericParametersAndArguments.html#requirement_list)
+> *约束集* → [*约束*](GenericParametersAndArguments.html#requirement) | [*约束*](GenericParametersAndArguments.html#requirement) **,** [*约束集*](GenericParametersAndArguments.html#requirement_list)
> *约束* → [*一致性约束*](GenericParametersAndArguments.html#conformance_requirement) | [*同类型约束*](GenericParametersAndArguments.html#same_type_requirement)
> *一致性约束* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) **:** [*类型标识*](..\chapter3\03_Types.html#type_identifier)
> *一致性约束* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) **:** [*协议合成类型*](..\chapter3\03_Types.html#protocol_composition_type)
-> *同类型约束* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) **==** [*类型标识*](..\chapter3\03_Types.html#type_identifier)
+> *同类型约束* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) **==** [*类型*](..\chapter3\03_Types.html#type_identifier)
-> 泛型实参子句语法
-> *(泛型参数子句Generic Argument Clause)* → **<** [*泛型参数列表*](GenericParametersAndArguments.html#generic_argument_list) **>**
-> *泛型参数列表* → [*泛型参数*](GenericParametersAndArguments.html#generic_argument) | [*泛型参数*](GenericParametersAndArguments.html#generic_argument) **,** [*泛型参数列表*](GenericParametersAndArguments.html#generic_argument_list)
+> 泛型实参从句语法
+> *(泛型参数从句Generic Argument Clause)* → **<** [*泛型参数集*](GenericParametersAndArguments.html#generic_argument_list) **>**
+> *泛型参数集* → [*泛型参数*](GenericParametersAndArguments.html#generic_argument) | [*泛型参数*](GenericParametersAndArguments.html#generic_argument) **,** [*泛型参数集*](GenericParametersAndArguments.html#generic_argument_list)
> *泛型参数* → [*类型*](..\chapter3\03_Types.html#type)
@@ -160,9 +237,8 @@ _________________
> *声明* → [*扩展声明*](..\chapter3\05_Declarations.html#extension_declaration)
> *声明* → [*下标脚本声明*](..\chapter3\05_Declarations.html#subscript_declaration)
> *声明* → [*运算符声明*](..\chapter3\05_Declarations.html#operator_declaration)
-> *声明(Declarations)列表* → [*声明*](..\chapter3\05_Declarations.html#declaration) [*声明(Declarations)列表*](..\chapter3\05_Declarations.html#declarations) _可选_
-> *声明描述符(Specifiers)列表* → [*声明描述符(Specifier)*](..\chapter3\05_Declarations.html#declaration_specifier) [*声明描述符(Specifiers)列表*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_
-> *声明描述符(Specifier)* → **class** | **mutating** | **nonmutating** | **override** | **static** | **unowned** | **unowned(safe)** | **unowned(unsafe)** | **weak**
+> *声明(Declarations)集* → [*声明*](..\chapter3\05_Declarations.html#declaration) [*声明(Declarations)集*](..\chapter3\05_Declarations.html#declarations) _可选_
+
@@ -177,7 +253,7 @@ _________________
> 导入(Import)声明语法
-> *导入声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **import** [*导入类型*](..\chapter3\05_Declarations.html#import_kind) _可选_ [*导入路径*](..\chapter3\05_Declarations.html#import_path)
+> *导入声明* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **import** [*导入类型*](..\chapter3\05_Declarations.html#import_kind) _可选_ [*导入路径*](..\chapter3\05_Declarations.html#import_path)
> *导入类型* → **typealias** | **struct** | **class** | **enum** | **protocol** | **var** | **func**
> *导入路径* → [*导入路径标识符*](..\chapter3\05_Declarations.html#import_path_identifier) | [*导入路径标识符*](..\chapter3\05_Declarations.html#import_path_identifier) **.** [*导入路径*](..\chapter3\05_Declarations.html#import_path)
> *导入路径标识符* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | [*运算符*](..\chapter3\02_Lexical_Structure.html#operator)
@@ -185,108 +261,117 @@ _________________
> 常数声明语法
-> *常量声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明描述符(Specifiers)列表*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **let** [*模式构造器列表*](..\chapter3\05_Declarations.html#pattern_initializer_list)
-> *模式构造器列表* → [*模式构造器*](..\chapter3\05_Declarations.html#pattern_initializer) | [*模式构造器*](..\chapter3\05_Declarations.html#pattern_initializer) **,** [*模式构造器列表*](..\chapter3\05_Declarations.html#pattern_initializer_list)
+> *常量声明* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修改符(Modifiers)集*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **let** [*模式构造器集*](..\chapter3\05_Declarations.html#pattern_initializer_list)
+> *模式构造器集* → [*模式构造器*](..\chapter3\05_Declarations.html#pattern_initializer) | [*模式构造器*](..\chapter3\05_Declarations.html#pattern_initializer) **,** [*模式构造器集*](..\chapter3\05_Declarations.html#pattern_initializer_list)
> *模式构造器* → [*模式*](..\chapter3\07_Patterns.html#pattern) [*构造器*](..\chapter3\05_Declarations.html#initializer) _可选_
> *构造器* → **=** [*表达式*](..\chapter3\04_Expressions.html#expression)
> 变量声明语法
-> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*模式构造器列表*](..\chapter3\05_Declarations.html#pattern_initializer_list)
+> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*模式构造器集*](..\chapter3\05_Declarations.html#pattern_initializer_list)
> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*代码块*](..\chapter3\05_Declarations.html#code_block)
> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*getter-setter块*](..\chapter3\05_Declarations.html#getter_setter_block)
> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*getter-setter关键字(Keyword)块*](..\chapter3\05_Declarations.html#getter_setter_keyword_block)
> *变量声明* → [*变量声明头(Head)*](..\chapter3\05_Declarations.html#variable_declaration_head) [*变量名*](..\chapter3\05_Declarations.html#variable_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*构造器*](..\chapter3\05_Declarations.html#initializer) _可选_ [*willSet-didSet代码块*](..\chapter3\05_Declarations.html#willSet_didSet_block)
-> *变量声明头(Head)* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明描述符(Specifiers)列表*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **var**
+> *变量声明头(Head)* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修改符(Modifers)集*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **var**
> *变量名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
-> *getter-setter块* → **{** [*getter子句*](..\chapter3\05_Declarations.html#getter_clause) [*setter子句*](..\chapter3\05_Declarations.html#setter_clause) _可选_ **}**
-> *getter-setter块* → **{** [*setter子句*](..\chapter3\05_Declarations.html#setter_clause) [*getter子句*](..\chapter3\05_Declarations.html#getter_clause) **}**
-> *getter子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **get** [*代码块*](..\chapter3\05_Declarations.html#code_block)
-> *setter子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **set** [*setter名称*](..\chapter3\05_Declarations.html#setter_name) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block)
+> *getter-setter块* → **{** [*getter从句*](..\chapter3\05_Declarations.html#getter_clause) [*setter从句*](..\chapter3\05_Declarations.html#setter_clause) _可选_ **}**
+> *getter-setter块* → **{** [*setter从句*](..\chapter3\05_Declarations.html#setter_clause) [*getter从句*](..\chapter3\05_Declarations.html#getter_clause) **}**
+> *getter从句* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **get** [*代码块*](..\chapter3\05_Declarations.html#code_block)
+> *setter从句* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **set** [*setter名称*](..\chapter3\05_Declarations.html#setter_name) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block)
> *setter名称* → **(** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) **)**
-> *getter-setter关键字(Keyword)块* → **{** [*getter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#getter_keyword_clause) [*setter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#setter_keyword_clause) _可选_ **}**
-> *getter-setter关键字(Keyword)块* → **{** [*setter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#setter_keyword_clause) [*getter关键字(Keyword)子句*](..\chapter3\05_Declarations.html#getter_keyword_clause) **}**
-> *getter关键字(Keyword)子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **get**
-> *setter关键字(Keyword)子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **set**
-> *willSet-didSet代码块* → **{** [*willSet子句*](..\chapter3\05_Declarations.html#willSet_clause) [*didSet子句*](..\chapter3\05_Declarations.html#didSet_clause) _可选_ **}**
-> *willSet-didSet代码块* → **{** [*didSet子句*](..\chapter3\05_Declarations.html#didSet_clause) [*willSet子句*](..\chapter3\05_Declarations.html#willSet_clause) **}**
-> *willSet子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **willSet** [*setter名称*](..\chapter3\05_Declarations.html#setter_name) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block)
-> *didSet子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **didSet** [*setter名称*](..\chapter3\05_Declarations.html#setter_name) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block)
+> *getter-setter关键字(Keyword)块* → **{** [*getter关键字(Keyword)从句*](..\chapter3\05_Declarations.html#getter_keyword_clause) [*setter关键字(Keyword)从句*](..\chapter3\05_Declarations.html#setter_keyword_clause) _可选_ **}**
+> *getter-setter关键字(Keyword)块* → **{** [*setter关键字(Keyword)从句*](..\chapter3\05_Declarations.html#setter_keyword_clause) [*getter关键字(Keyword)从句*](..\chapter3\05_Declarations.html#getter_keyword_clause) **}**
+> *getter关键字(Keyword)从句* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **get**
+> *setter关键字(Keyword)从句* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **set**
+> *willSet-didSet代码块* → **{** [*willSet从句*](..\chapter3\05_Declarations.html#willSet_clause) [*didSet从句*](..\chapter3\05_Declarations.html#didSet_clause) _可选_ **}**
+> *willSet-didSet代码块* → **{** [*didSet从句*](..\chapter3\05_Declarations.html#didSet_clause) [*willSet从句*](..\chapter3\05_Declarations.html#willSet_clause) **}**
+> *willSet从句* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **willSet** [*setter名称*](..\chapter3\05_Declarations.html#setter_name) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block)
+> *didSet从句* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **didSet** [*setter名称*](..\chapter3\05_Declarations.html#setter_name) _可选_ [*代码块*](..\chapter3\05_Declarations.html#code_block)
> 类型别名声明语法
> *类型别名声明* → [*类型别名头(Head)*](..\chapter3\05_Declarations.html#typealias_head) [*类型别名赋值*](..\chapter3\05_Declarations.html#typealias_assignment)
-> *类型别名头(Head)* → **typealias** [*类型别名名称*](..\chapter3\05_Declarations.html#typealias_name)
+> *类型别名头(Head)* → [*属性*](TODO) _可选_ [*访问级别修改符(access-level-modifier)*](TODO) **typealias** [*类型别名名称*](..\chapter3\05_Declarations.html#typealias_name)
> *类型别名名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
> *类型别名赋值* → **=** [*类型*](..\chapter3\03_Types.html#type)
> 函数声明语法
-> *函数声明* → [*函数头*](..\chapter3\05_Declarations.html#function_head) [*函数名*](..\chapter3\05_Declarations.html#function_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*函数签名(Signature)*](..\chapter3\05_Declarations.html#function_signature) [*函数体*](..\chapter3\05_Declarations.html#function_body)
-> *函数头* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明描述符(Specifiers)列表*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **func**
+> *函数声明* → [*函数头*](..\chapter3\05_Declarations.html#function_head) [*函数名*](..\chapter3\05_Declarations.html#function_name) [*泛型参数从句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*函数签名(Signature)*](..\chapter3\05_Declarations.html#function_signature) [*函数体*](..\chapter3\05_Declarations.html#function_body)
+> *函数头* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明描述符(Specifiers)集*](..\chapter3\05_Declarations.html#declaration_specifiers) _可选_ **func**
> *函数名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | [*运算符*](..\chapter3\02_Lexical_Structure.html#operator)
-> *函数签名(Signature)* → [*parameter-clauses*](..\chapter3\05_Declarations.html#parameter_clauses) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_
-> *函数结果* → **->** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type)
+> *函数签名(Signature)* → [*parameter-clauses*](..\chapter3\05_Declarations.html#parameter_clauses) **throws** _可选_ [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_
+
+> *函数签名(Signature)* → [*parameter-clauses*](..\chapter3\05_Declarations.html#parameter_clauses) **rethrows** [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_
+> *函数结果* → **->** [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type)
> *函数体* → [*代码块*](..\chapter3\05_Declarations.html#code_block)
-> *parameter-clauses* → [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*parameter-clauses*](..\chapter3\05_Declarations.html#parameter_clauses) _可选_
-> *参数子句* → **(** **)** | **(** [*参数列表*](..\chapter3\05_Declarations.html#parameter_list) **...** _可选_ **)**
-> *参数列表* → [*参数*](..\chapter3\05_Declarations.html#parameter) | [*参数*](..\chapter3\05_Declarations.html#parameter) **,** [*参数列表*](..\chapter3\05_Declarations.html#parameter_list)
-> *参数* → **inout** _可选_ **let** _可选_ **#** _可选_ [*参数名*](..\chapter3\05_Declarations.html#parameter_name) [*本地参数名*](..\chapter3\05_Declarations.html#local_parameter_name) _可选_ [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*默认参数子句*](..\chapter3\05_Declarations.html#default_argument_clause) _可选_
-> *参数* → **inout** _可选_ **var** **#** _可选_ [*参数名*](..\chapter3\05_Declarations.html#parameter_name) [*本地参数名*](..\chapter3\05_Declarations.html#local_parameter_name) _可选_ [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*默认参数子句*](..\chapter3\05_Declarations.html#default_argument_clause) _可选_
-> *参数* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type)
-> *参数名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | **_**
+> *参数从句* → [*参数从句*](..\chapter3\05_Declarations.html#parameter_clause) [*parameter-clauses*](..\chapter3\05_Declarations.html#parameter_clauses) _可选_
+> *参数从句* → **(** **)** | **(** [*参数集*](..\chapter3\05_Declarations.html#parameter_list) **...** _可选_ **)**
+> *参数集* → [*参数*](..\chapter3\05_Declarations.html#parameter) | [*参数*](..\chapter3\05_Declarations.html#parameter) **,** [*参数集*](..\chapter3\05_Declarations.html#parameter_list)
+> *参数* → **inout** _可选_ **let** _可选_ [*外部参数名*](..\chapter3\05_Declarations.html#parameter_name) _可选_ [*本地参数名*](..\chapter3\05_Declarations.html#local_parameter_name) _可选_ [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*默认参数从句*](..\chapter3\05_Declarations.html#default_argument_clause) _可选_
+> *参数* → **inout** _可选_ **var** [*外部参数名*](..\chapter3\05_Declarations.html#parameter_name) [*本地参数名*](..\chapter3\05_Declarations.html#local_parameter_name) _可选_ [*类型注解*](..\chapter3\03_Types.html#type_annotation) [*默认参数从句*](..\chapter3\05_Declarations.html#default_argument_clause) _可选_
+> *参数* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type)
+> *外部参数名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | **_**
> *本地参数名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | **_**
-> *默认参数子句* → **=** [*表达式*](..\chapter3\04_Expressions.html#expression)
+> *默认参数从句* → **=** [*表达式*](..\chapter3\04_Expressions.html#expression)
> 枚举声明语法
-> *枚举声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*联合式枚举*](..\chapter3\05_Declarations.html#union_style_enum) | [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*原始值式枚举*](..\chapter3\05_Declarations.html#raw_value_style_enum)
-> *联合式枚举* → [*枚举名*](..\chapter3\05_Declarations.html#enum_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ **{** [*union-style-enum-members*](..\chapter3\05_Declarations.html#union_style_enum_members) _可选_ **}**
-> *union-style-enum-members* → [*union-style-enum-member*](..\chapter3\05_Declarations.html#union_style_enum_member) [*union-style-enum-members*](..\chapter3\05_Declarations.html#union_style_enum_members) _可选_
-> *union-style-enum-member* → [*声明*](..\chapter3\05_Declarations.html#declaration) | [*联合式(Union Style)的枚举case子句*](..\chapter3\05_Declarations.html#union_style_enum_case_clause)
-> *联合式(Union Style)的枚举case子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **case** [*联合式(Union Style)的枚举case列表*](..\chapter3\05_Declarations.html#union_style_enum_case_list)
-> *联合式(Union Style)的枚举case列表* → [*联合式(Union Style)的case*](..\chapter3\05_Declarations.html#union_style_enum_case) | [*联合式(Union Style)的case*](..\chapter3\05_Declarations.html#union_style_enum_case) **,** [*联合式(Union Style)的枚举case列表*](..\chapter3\05_Declarations.html#union_style_enum_case_list)
-> *联合式(Union Style)的case* → [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*元组类型*](..\chapter3\03_Types.html#tuple_type) _可选_
+> *枚举声明* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*访问级别修改器(access-level-modifier)*](TODO) _可选_ [*联合式枚举*](..\chapter3\05_Declarations.html#union_style_enum)
+
+> *枚举声明* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*访问级别修改器(access-level-modifier)*](TODO) _可选_ [*原始值式枚举(raw-value-style-enum)*](TODO)
+
+> *联合式枚举* → **enum** [*枚举名*](..\chapter3\05_Declarations.html#enum_name) [*泛型参数从句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承从句(type-inheritance-clause)*](TODO) _可选_ **{** [*联合样式枚举成员*](..\chapter3\05_Declarations.html#union_style_enum_members) _可选_ **}**
+
+> *联合样式枚举成员* → [*union-style-enum-member*](..\chapter3\05_Declarations.html#union_style_enum_member) [*联合样式枚举成员*](..\chapter3\05_Declarations.html#union_style_enum_members) _可选_
+
+> *联合样式枚举成员* → [*声明*](..\chapter3\05_Declarations.html#declaration) | [*联合式(Union Style)的枚举case从句*](..\chapter3\05_Declarations.html#union_style_enum_case_clause)
+
+> *联合式(Union Style)的枚举case从句* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **case** [*联合式(Union Style)的枚举case集*](..\chapter3\05_Declarations.html#union_style_enum_case_list)
+> *联合式(Union Style)的枚举case集* → [*联合式(Union Style)的case*](..\chapter3\05_Declarations.html#union_style_enum_case) | [*联合式(Union Style)的case*](..\chapter3\05_Declarations.html#union_style_enum_case) **,** [*联合式(Union Style)的枚举case集*](..\chapter3\05_Declarations.html#union_style_enum_case_list)
+> *联合式(Union Style)的枚举case* → [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*元组类型*](..\chapter3\03_Types.html#tuple_type) _可选_
> *枚举名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
> *枚举的case名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
-> *原始值式枚举* → [*枚举名*](..\chapter3\05_Declarations.html#enum_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ **:** [*类型标识*](..\chapter3\03_Types.html#type_identifier) **{** [*原始值式枚举成员列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_members) _可选_ **}**
-> *原始值式枚举成员列表* → [*原始值式枚举成员*](..\chapter3\05_Declarations.html#raw_value_style_enum_member) [*原始值式枚举成员列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_members) _可选_
-> *原始值式枚举成员* → [*声明*](..\chapter3\05_Declarations.html#declaration) | [*原始值式枚举case子句*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_clause)
-> *原始值式枚举case子句* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **case** [*原始值式枚举case列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_list)
-> *原始值式枚举case列表* → [*原始值式枚举case*](..\chapter3\05_Declarations.html#raw_value_style_enum_case) | [*原始值式枚举case*](..\chapter3\05_Declarations.html#raw_value_style_enum_case) **,** [*原始值式枚举case列表*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_list)
+> *原始值式枚举* → **enum** [*枚举名*](..\chapter3\05_Declarations.html#enum_name) [*泛型参数从句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ **:** [*类型标识*](..\chapter3\03_Types.html#type_identifier) **{** [*原始值式枚举成员集*](..\chapter3\05_Declarations.html#raw_value_style_enum_members) _可选_ **}**
+> *原始值式枚举成员集* → [*原始值式枚举成员*](..\chapter3\05_Declarations.html#raw_value_style_enum_member) [*原始值式枚举成员集*](..\chapter3\05_Declarations.html#raw_value_style_enum_members) _可选_
+> *原始值式枚举成员* → [*声明*](..\chapter3\05_Declarations.html#declaration) | [*原始值式枚举case从句*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_clause)
+> *原始值式枚举case从句* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **case** [*原始值式枚举case集*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_list)
+> *原始值式枚举case集* → [*原始值式枚举case*](..\chapter3\05_Declarations.html#raw_value_style_enum_case) | [*原始值式枚举case*](..\chapter3\05_Declarations.html#raw_value_style_enum_case) **,** [*原始值式枚举case集*](..\chapter3\05_Declarations.html#raw_value_style_enum_case_list)
> *原始值式枚举case* → [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*原始值赋值*](..\chapter3\05_Declarations.html#raw_value_assignment) _可选_
-> *原始值赋值* → **=** [*字面量*](..\chapter3\02_Lexical_Structure.html#literal)
+> *原始值赋值* → **=** [*字面量*](..\chapter3\02_Lexical_Structure.html#literal)
+> *原始值字面量(raw-value-literal)* → [*数值字面量*](TODO) | [*字符串字面量*](TODO) | [*布尔字面量*](TODO)
> 结构体声明语法
-> *结构体声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **struct** [*结构体名称*](..\chapter3\05_Declarations.html#struct_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*结构体主体*](..\chapter3\05_Declarations.html#struct_body)
+> *结构体声明* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*访问级别修改器(access-level-modifier)*](TODO) _可选_ **struct** [*结构体名称*](..\chapter3\05_Declarations.html#struct_name) [*泛型参数从句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承从句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*结构体主体*](..\chapter3\05_Declarations.html#struct_body)
> *结构体名称* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
-> *结构体主体* → **{** [*声明(Declarations)列表*](..\chapter3\05_Declarations.html#declarations) _可选_ **}**
+> *结构体主体* → **{** [*声明(Declarations)集*](..\chapter3\05_Declarations.html#declarations) _可选_ **}**
> 类声明语法
-> *类声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **class** [*类名*](..\chapter3\05_Declarations.html#class_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*类主体*](..\chapter3\05_Declarations.html#class_body)
+> *类声明* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*访问级别修改器(access-level-modifier)*](TODO) **class** [*类名*](..\chapter3\05_Declarations.html#class_name) [*泛型参数从句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*类型继承从句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*类主体*](..\chapter3\05_Declarations.html#class_body)
> *类名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
-> *类主体* → **{** [*声明(Declarations)列表*](..\chapter3\05_Declarations.html#declarations) _可选_ **}**
+> *类主体* → **{** [*声明(Declarations)集*](..\chapter3\05_Declarations.html#declarations) _可选_ **}**
> 协议(Protocol)声明语法
-> *协议声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **protocol** [*协议名*](..\chapter3\05_Declarations.html#protocol_name) [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*协议主体*](..\chapter3\05_Declarations.html#protocol_body)
+> *协议声明* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_[*访问级别修改器(access-level-modifier)*](TODO) **protocol** [*协议名*](..\chapter3\05_Declarations.html#protocol_name) [*类型继承从句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*协议主体*](..\chapter3\05_Declarations.html#protocol_body)
> *协议名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
-> *协议主体* → **{** [*协议成员声明(Declarations)列表*](..\chapter3\05_Declarations.html#protocol_member_declarations) _可选_ **}**
+> *协议主体* → **{** [*协议成员声明(Declarations)集*](..\chapter3\05_Declarations.html#protocol_member_declarations) _可选_ **}**
> *协议成员声明* → [*协议属性声明*](..\chapter3\05_Declarations.html#protocol_property_declaration)
> *协议成员声明* → [*协议方法声明*](..\chapter3\05_Declarations.html#protocol_method_declaration)
> *协议成员声明* → [*协议构造器声明*](..\chapter3\05_Declarations.html#protocol_initializer_declaration)
> *协议成员声明* → [*协议下标脚本声明*](..\chapter3\05_Declarations.html#protocol_subscript_declaration)
> *协议成员声明* → [*协议关联类型声明*](..\chapter3\05_Declarations.html#protocol_associated_type_declaration)
-> *协议成员声明(Declarations)列表* → [*协议成员声明*](..\chapter3\05_Declarations.html#protocol_member_declaration) [*协议成员声明(Declarations)列表*](..\chapter3\05_Declarations.html#protocol_member_declarations) _可选_
+> *协议成员声明(Declarations)集* → [*协议成员声明*](..\chapter3\05_Declarations.html#protocol_member_declaration) [*协议成员声明(Declarations)集*](..\chapter3\05_Declarations.html#protocol_member_declarations) _可选_
@@ -296,12 +381,12 @@ _________________
> 协议方法声明语法
-> *协议方法声明* → [*函数头*](..\chapter3\05_Declarations.html#function_head) [*函数名*](..\chapter3\05_Declarations.html#function_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*函数签名(Signature)*](..\chapter3\05_Declarations.html#function_signature)
+> *协议方法声明* → [*函数头*](..\chapter3\05_Declarations.html#function_head) [*函数名*](..\chapter3\05_Declarations.html#function_name) [*泛型参数从句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*函数签名(Signature)*](..\chapter3\05_Declarations.html#function_signature)
> 协议构造器声明语法
-> *协议构造器声明* → [*构造器头(Head)*](..\chapter3\05_Declarations.html#initializer_head) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause)
+> *协议构造器声明* → [*构造器头(Head)*](..\chapter3\05_Declarations.html#initializer_head) [*泛型参数从句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*参数从句*](..\chapter3\05_Declarations.html#parameter_clause)
@@ -311,25 +396,29 @@ _________________
> 协议关联类型声明语法
-> *协议关联类型声明* → [*类型别名头(Head)*](..\chapter3\05_Declarations.html#typealias_head) [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*类型别名赋值*](..\chapter3\05_Declarations.html#typealias_assignment) _可选_
+> *协议关联类型声明* → [*类型别名头(Head)*](..\chapter3\05_Declarations.html#typealias_head) [*类型继承从句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*类型别名赋值*](..\chapter3\05_Declarations.html#typealias_assignment) _可选_
> 构造器声明语法
-> *构造器声明* → [*构造器头(Head)*](..\chapter3\05_Declarations.html#initializer_head) [*泛型参数子句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*构造器主体*](..\chapter3\05_Declarations.html#initializer_body)
-> *构造器头(Head)* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **convenience** _可选_ **init**
+> *构造器声明* → [*构造器头(Head)*](..\chapter3\05_Declarations.html#initializer_head) [*泛型参数从句*](GenericParametersAndArguments.html#generic_parameter_clause) _可选_ [*参数从句*](..\chapter3\05_Declarations.html#parameter_clause) [*构造器主体*](..\chapter3\05_Declarations.html#initializer_body)
+> *构造器头(Head)* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修改器集(declaration-modifiers)*](TODO) _可选_ **init**
+> *构造器头(Head)* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修改器集(declaration-modifiers)*](TODO) _可选_ **init ?**
+
+> *构造器头(Head)* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修改器集(declaration-modifiers)*](TODO) _可选_ **init !**
+
> *构造器主体* → [*代码块*](..\chapter3\05_Declarations.html#code_block)
> 析构器声明语法
-> *析构器声明* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **deinit** [*代码块*](..\chapter3\05_Declarations.html#code_block)
+> *析构器声明* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **deinit** [*代码块*](..\chapter3\05_Declarations.html#code_block)
> 扩展(Extension)声明语法
-> *扩展声明* → **extension** [*类型标识*](..\chapter3\03_Types.html#type_identifier) [*类型继承子句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*extension-body*](..\chapter3\05_Declarations.html#extension_body)
-> *extension-body* → **{** [*声明(Declarations)列表*](..\chapter3\05_Declarations.html#declarations) _可选_ **}**
+> *扩展声明* → [*访问级别修改器*](TODO) _可选_ **extension** [*类型标识*](..\chapter3\03_Types.html#type_identifier) [*类型继承从句*](..\chapter3\03_Types.html#type_inheritance_clause) _可选_ [*extension-body*](..\chapter3\05_Declarations.html#extension_body)
+> *extension-body* → **{** [*声明(Declarations)集*](..\chapter3\05_Declarations.html#declarations) _可选_ **}**
@@ -337,32 +426,51 @@ _________________
> *下标脚本声明* → [*下标脚本头(Head)*](..\chapter3\05_Declarations.html#subscript_head) [*下标脚本结果(Result)*](..\chapter3\05_Declarations.html#subscript_result) [*代码块*](..\chapter3\05_Declarations.html#code_block)
> *下标脚本声明* → [*下标脚本头(Head)*](..\chapter3\05_Declarations.html#subscript_head) [*下标脚本结果(Result)*](..\chapter3\05_Declarations.html#subscript_result) [*getter-setter块*](..\chapter3\05_Declarations.html#getter_setter_block)
> *下标脚本声明* → [*下标脚本头(Head)*](..\chapter3\05_Declarations.html#subscript_head) [*下标脚本结果(Result)*](..\chapter3\05_Declarations.html#subscript_result) [*getter-setter关键字(Keyword)块*](..\chapter3\05_Declarations.html#getter_setter_keyword_block)
-> *下标脚本头(Head)* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **subscript** [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause)
-> *下标脚本结果(Result)* → **->** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type)
+> *下标脚本头(Head)* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*声明修改器(declaration-modifiers)*](TODO) _可选_ **subscript** [*参数从句*](..\chapter3\05_Declarations.html#parameter_clause)
+> *下标脚本结果(Result)* → **->** [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type)
> 运算符声明语法
> *运算符声明* → [*前置运算符声明*](..\chapter3\05_Declarations.html#prefix_operator_declaration) | [*后置运算符声明*](..\chapter3\05_Declarations.html#postfix_operator_declaration) | [*中置运算符声明*](..\chapter3\05_Declarations.html#infix_operator_declaration)
-> *前置运算符声明* → **运算符** **prefix** [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) **{** **}**
-> *后置运算符声明* → **运算符** **postfix** [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) **{** **}**
-> *中置运算符声明* → **运算符** **infix** [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) **{** [*中置运算符属性*](..\chapter3\05_Declarations.html#infix_operator_attributes) _可选_ **}**
-> *中置运算符属性* → [*优先级子句*](..\chapter3\05_Declarations.html#precedence_clause) _可选_ [*结和性子句*](..\chapter3\05_Declarations.html#associativity_clause) _可选_
-> *优先级子句* → **precedence** [*优先级水平*](..\chapter3\05_Declarations.html#precedence_level)
-> *优先级水平* → 数值 0 到 255
-> *结和性子句* → **associativity** [*结和性*](..\chapter3\05_Declarations.html#associativity)
+> *前置运算符声明* → **prefix** **运算符** [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) **{** **}**
+> *后置运算符声明* → **postfix** **运算符** [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) **{** **}**
+> *中置运算符声明* → **infix** **运算符** [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) **{** [*中置运算符属性集*](..\chapter3\05_Declarations.html#infix_operator_attributes) _可选_ **}**
+> *中置运算符属性集* → [*优先级从句*](..\chapter3\05_Declarations.html#precedence_clause) _可选_ [*结和性从句*](..\chapter3\05_Declarations.html#associativity_clause) _可选_
+> *优先级从句* → **precedence** [*优先级水平*](..\chapter3\05_Declarations.html#precedence_level)
+> *优先级水平* → 数值 0 到 255,首末项包括在内
+> *结和性从句* → **associativity** [*结和性*](..\chapter3\05_Declarations.html#associativity)
> *结和性* → **left** | **right** | **none**
+
+声明修改器语法
+> *声明修改器* → **类** | **便捷(convenience)** | **动态(dynamic)** | **final** | **中置(infix)** | **lazy** | **可变(mutating)** | **不可变(nonmutating)** | **可选(optional)** | **改写(override)** | **后置** | **前置** | **required** | **static** | **unowned** | **unowned(safe)** | **unowned(unsafe)** | **弱(weak)**
+
+> *声明修改器* → [*访问级别声明器(access-level-modifier)*](TODO)
+
+> *声明修改集* → [*声明修改器*](TODO) [*声明修改器集*](TODO) _可选_
+
+> *访问级别修改器* → **内部的** | **内部的(set)**
+
+> *访问级别修改器* → **私有的** | **私有的(set)**
+
+> *访问级别修改器* → **公共的**
+| **公共的(set)**
+
+> *访问级别修改器集* →[*访问级别修改器*](TODO) [*访问级别修改器集*](TODO) _可选_
+
## 模式
> 模式(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#identifier_pattern) [*类型注解*](..\chapter3\03_Types.html#type_annotati Value Bindingon ) _可选_
> *模式* → [*值绑定模式*](..\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)
-> *模式* → [*type-casting-pattern*](..\chapter3\07_Patterns.html#type_casting_pattern)
+
+> *模式* → [*枚举个例模式*](..\chapter3\07_Patterns.html#enum_case_pattern)
+> *模式* → [*可选模式*](TODO)
+> *模式* → [*类型转换模式*](..\chapter3\07_Patterns.html#type_casting_pattern)
> *模式* → [*表达式模式*](..\chapter3\07_Patterns.html#expression_pattern)
@@ -383,19 +491,24 @@ _________________
> 元组模式语法
-> *元组模式* → **(** [*元组模式元素列表*](..\chapter3\07_Patterns.html#tuple_pattern_element_list) _可选_ **)**
-> *元组模式元素列表* → [*元组模式元素*](..\chapter3\07_Patterns.html#tuple_pattern_element) | [*元组模式元素*](..\chapter3\07_Patterns.html#tuple_pattern_element) **,** [*元组模式元素列表*](..\chapter3\07_Patterns.html#tuple_pattern_element_list)
+> *元组模式* → **(** [*元组模式元素集*](..\chapter3\07_Patterns.html#tuple_pattern_element_list) _可选_ **)**
+> *元组模式元素集* → [*元组模式元素*](..\chapter3\07_Patterns.html#tuple_pattern_element) | [*元组模式元素*](..\chapter3\07_Patterns.html#tuple_pattern_element) **,** [*元组模式元素集*](..\chapter3\07_Patterns.html#tuple_pattern_element_list)
> *元组模式元素* → [*模式*](..\chapter3\07_Patterns.html#pattern)
> 枚举用例模式语法
-> *enum-case-pattern* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) _可选_ **.** [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*元组模式*](..\chapter3\07_Patterns.html#tuple_pattern) _可选_
+> *enum-case-pattern* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) _可选_ **.** [*枚举的case名*](..\chapter3\05_Declarations.html#enum_case_name) [*元组模式*](..\chapter3\07_Patterns.html#tuple_pattern) _可选_
+
+
+> 可选模式语法
+> *可选模式* → [*识别符模式*](TODO) **?**
+
> 类型转换模式语法
-> *type-casting-pattern* → [*is模式*](..\chapter3\07_Patterns.html#is_pattern) | [*as模式*](..\chapter3\07_Patterns.html#as_pattern)
+> *类型转换模式(type-casting-pattern)* → [*is模式*](..\chapter3\07_Patterns.html#is_pattern) | [*as模式*](..\chapter3\07_Patterns.html#as_pattern)
> *is模式* → **is** [*类型*](..\chapter3\03_Types.html#type)
> *as模式* → [*模式*](..\chapter3\07_Patterns.html#pattern) **as** [*类型*](..\chapter3\03_Types.html#type)
@@ -405,17 +518,17 @@ _________________
> *表达式模式* → [*表达式*](..\chapter3\04_Expressions.html#expression)
-## 特性
+## 属性
-> 特性语法
-> *特色* → **@** [*特性名*](..\chapter3\06_Attributes.html#attribute_name) [*特性参数子句*](..\chapter3\06_Attributes.html#attribute_argument_clause) _可选_
-> *特性名* → [*标识符*](..\chapter3\02_Lexical_Structure.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) _可选_ **}**
+> 属性语法
+> *属性* → **@** [*属性名*](..\chapter3\06_Attributes.html#attribute_name) [*属性参数从句*](..\chapter3\06_Attributes.html#attribute_argument_clause) _可选_
+> *属性名* → [*标识符*](..\chapter3\02_Lexical_Structure.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) _可选_ **}**
> *平衡令牌* → **任意标识符, 关键字, 字面量或运算符**
> *平衡令牌* → **任意标点除了(, ), [, ], {, 或 }**
@@ -423,24 +536,29 @@ _________________
## 表达式
> 表达式语法
-> *表达式* → [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) [*二元表达式列表*](..\chapter3\04_Expressions.html#binary_expressions) _可选_
-> *表达式列表* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*表达式*](..\chapter3\04_Expressions.html#expression) **,** [*表达式列表*](..\chapter3\04_Expressions.html#expression_list)
+> *表达式* → [*try-operator*](TODO) _可选_ [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression) [*二元表达式集*](..\chapter3\04_Expressions.html#binary_expressions) _可选_
+> *表达式集* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*表达式*](..\chapter3\04_Expressions.html#expression) **,** [*表达式集*](..\chapter3\04_Expressions.html#expression_list)
> 前置表达式语法
> *前置表达式* → [*前置运算符*](..\chapter3\02_Lexical_Structure.html#prefix_operator) _可选_ [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression)
> *前置表达式* → [*写入写出(in-out)表达式*](..\chapter3\04_Expressions.html#in_out_expression)
-> *写入写出(in-out)表达式* → **&** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
+> *写入写出(in-out)表达式* → **&** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
+
+
+> try表达式语法
+> *try-operator* → **try** | **try !**
+
> 二元表达式语法
> *二元表达式* → [*二元运算符*](..\chapter3\02_Lexical_Structure.html#binary_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
-> *二元表达式* → [*赋值运算符*](..\chapter3\04_Expressions.html#assignment_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
-> *二元表达式* → [*条件运算符*](..\chapter3\04_Expressions.html#conditional_operator) [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
+> *二元表达式* → [*赋值运算符*](..\chapter3\04_Expressions.html#assignment_operator) [*try运算符*](TODO) _可选_ [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
+> *二元表达式* → [*条件运算符*](..\chapter3\04_Expressions.html#conditional_operator) [*try运算符*](TODO) _可选_ [*前置表达式*](..\chapter3\04_Expressions.html#prefix_expression)
> *二元表达式* → [*类型转换运算符*](..\chapter3\04_Expressions.html#type_casting_operator)
-> *二元表达式列表* → [*二元表达式*](..\chapter3\04_Expressions.html#binary_expression) [*二元表达式列表*](..\chapter3\04_Expressions.html#binary_expressions) _可选_
+> *二元表达式集* → [*二元表达式*](..\chapter3\04_Expressions.html#binary_expression) [*二元表达式集*](..\chapter3\04_Expressions.html#binary_expressions) _可选_
@@ -455,12 +573,20 @@ _________________
> 类型转换运算符语法
-> *类型转换运算符* → **is** [*类型*](..\chapter3\03_Types.html#type) | **as** **?** _可选_ [*类型*](..\chapter3\03_Types.html#type)
+> *类型转换运算符* → **is** [*类型*](..\chapter3\03_Types.html#type)
+
+> *类型转换运算符* → **as** [*类型*](..\chapter3\03_Types.html#type)
+
+> *类型转换运算符* → **as ?** [*类型*](..\chapter3\03_Types.html#type)
+
+> *类型转换运算符* → **as !** [*类型*](..\chapter3\03_Types.html#type)
+
+
> 主表达式语法
-> *主表达式* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_
+> *主表达式* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) [*泛型参数从句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_
> *主表达式* → [*字面量表达式*](..\chapter3\04_Expressions.html#literal_expression)
> *主表达式* → [*self表达式*](..\chapter3\04_Expressions.html#self_expression)
> *主表达式* → [*超类表达式*](..\chapter3\04_Expressions.html#superclass_expression)
@@ -475,11 +601,11 @@ _________________
> *字面量表达式* → [*字面量*](..\chapter3\02_Lexical_Structure.html#literal)
> *字面量表达式* → [*数组字面量*](..\chapter3\04_Expressions.html#array_literal) | [*字典字面量*](..\chapter3\04_Expressions.html#dictionary_literal)
> *字面量表达式* → **__FILE__** | **__LINE__** | **__COLUMN__** | **__FUNCTION__**
-> *数组字面量* → **[** [*数组字面量项列表*](..\chapter3\04_Expressions.html#array_literal_items) _可选_ **]**
-> *数组字面量项列表* → [*数组字面量项*](..\chapter3\04_Expressions.html#array_literal_item) **,** _可选_ | [*数组字面量项*](..\chapter3\04_Expressions.html#array_literal_item) **,** [*数组字面量项列表*](..\chapter3\04_Expressions.html#array_literal_items)
+> *数组字面量* → **[** [*数组字面量项集*](..\chapter3\04_Expressions.html#array_literal_items) _可选_ **]**
+> *数组字面量项集* → [*数组字面量项*](..\chapter3\04_Expressions.html#array_literal_item) **,** _可选_ | [*数组字面量项*](..\chapter3\04_Expressions.html#array_literal_item) **,** [*数组字面量项集*](..\chapter3\04_Expressions.html#array_literal_items)
> *数组字面量项* → [*表达式*](..\chapter3\04_Expressions.html#expression)
-> *字典字面量* → **[** [*字典字面量项列表*](..\chapter3\04_Expressions.html#dictionary_literal_items) **]** | **[** **:** **]**
-> *字典字面量项列表* → [*字典字面量项*](..\chapter3\04_Expressions.html#dictionary_literal_item) **,** _可选_ | [*字典字面量项*](..\chapter3\04_Expressions.html#dictionary_literal_item) **,** [*字典字面量项列表*](..\chapter3\04_Expressions.html#dictionary_literal_items)
+> *字典字面量* → **[** [*字典字面量项集*](..\chapter3\04_Expressions.html#dictionary_literal_items) **]** | **[** **:** **]**
+> *字典字面量项集* → [*字典字面量项*](..\chapter3\04_Expressions.html#dictionary_literal_item) **,** _可选_ | [*字典字面量项*](..\chapter3\04_Expressions.html#dictionary_literal_item) **,** [*字典字面量项集*](..\chapter3\04_Expressions.html#dictionary_literal_items)
> *字典字面量项* → [*表达式*](..\chapter3\04_Expressions.html#expression) **:** [*表达式*](..\chapter3\04_Expressions.html#expression)
@@ -502,12 +628,12 @@ _________________
> 闭包表达式语法
> *闭包表达式* → **{** [*闭包签名(Signational)*](..\chapter3\04_Expressions.html#closure_signature) _可选_ [*多条语句(Statements)*](..\chapter3\10_Statements.html#statements) **}**
-> *闭包签名(Signational)* → [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in**
-> *闭包签名(Signational)* → [*标识符列表*](..\chapter3\02_Lexical_Structure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in**
-> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) [*参数子句*](..\chapter3\05_Declarations.html#parameter_clause) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in**
-> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) [*标识符列表*](..\chapter3\02_Lexical_Structure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in**
-> *闭包签名(Signational)* → [*捕获(Capature)列表*](..\chapter3\04_Expressions.html#capture_list) **in**
-> *捕获(Capature)列表* → **[** [*捕获(Capature)说明符*](..\chapter3\04_Expressions.html#capture_specifier) [*表达式*](..\chapter3\04_Expressions.html#expression) **]**
+> *闭包签名(Signational)* → [*参数从句*](..\chapter3\05_Declarations.html#parameter_clause) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in**
+> *闭包签名(Signational)* → [*标识符集*](..\chapter3\02_Lexical_Structure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in**
+> *闭包签名(Signational)* → [*捕获(Capature)集*](..\chapter3\04_Expressions.html#capture_list) [*参数从句*](..\chapter3\05_Declarations.html#parameter_clause) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in**
+> *闭包签名(Signational)* → [*捕获(Capature)集*](..\chapter3\04_Expressions.html#capture_list) [*标识符集*](..\chapter3\02_Lexical_Structure.html#identifier_list) [*函数结果*](..\chapter3\05_Declarations.html#function_result) _可选_ **in**
+> *闭包签名(Signational)* → [*捕获(Capature)集*](..\chapter3\04_Expressions.html#capture_list) **in**
+> *捕获(Capature)集* → **[** [*捕获(Capature)说明符*](..\chapter3\04_Expressions.html#capture_specifier) [*表达式*](..\chapter3\04_Expressions.html#expression) **]**
> *捕获(Capature)说明符* → **weak** | **unowned** | **unowned(safe)** | **unowned(unsafe)**
@@ -518,8 +644,8 @@ _________________
> 圆括号表达式(Parenthesized Expression)语法
-> *圆括号表达式* → **(** [*表达式元素列表*](..\chapter3\04_Expressions.html#expression_element_list) _可选_ **)**
-> *表达式元素列表* → [*表达式元素*](..\chapter3\04_Expressions.html#expression_element) | [*表达式元素*](..\chapter3\04_Expressions.html#expression_element) **,** [*表达式元素列表*](..\chapter3\04_Expressions.html#expression_element_list)
+> *圆括号表达式* → **(** [*表达式元素集*](..\chapter3\04_Expressions.html#expression_element_list) _可选_ **)**
+> *表达式元素集* → [*表达式元素*](..\chapter3\04_Expressions.html#expression_element) | [*表达式元素*](..\chapter3\04_Expressions.html#expression_element) **,** [*表达式元素集*](..\chapter3\04_Expressions.html#expression_element_list)
> *表达式元素* → [*表达式*](..\chapter3\04_Expressions.html#expression) | [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) **:** [*表达式*](..\chapter3\04_Expressions.html#expression)
@@ -557,7 +683,7 @@ _________________
> 显式成员表达式语法
> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit)
-> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_
+> *显示成员表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **.** [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) [*泛型参数从句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_
@@ -572,7 +698,7 @@ _________________
> 附属脚本表达式语法
-> *附属脚本表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **[** [*表达式列表*](..\chapter3\04_Expressions.html#expression_list) **]**
+> *附属脚本表达式* → [*后置表达式*](..\chapter3\04_Expressions.html#postfix_expression) **[** [*表达式集*](..\chapter3\04_Expressions.html#expression_list) **]**
@@ -588,11 +714,14 @@ _________________
## 词法结构
> 标识符语法
-> *标识符* → [*标识符头(Head)*](..\chapter3\02_Lexical_Structure.html#identifier_head) [*标识符字符列表*](..\chapter3\02_Lexical_Structure.html#identifier_characters) _可选_
-> *标识符* → **`** [*标识符头(Head)*](..\chapter3\02_Lexical_Structure.html#identifier_head) [*标识符字符列表*](..\chapter3\02_Lexical_Structure.html#identifier_characters) _可选_ **`**
+> *标识符* → [*标识符头(Head)*](..\chapter3\02_Lexical_Structure.html#identifier_head) [*标识符字符集*](..\chapter3\02_Lexical_Structure.html#identifier_characters) _可选_
+> *标识符* → [*标识符头(Head)*](..\chapter3\02_Lexical_Structure.html#identifier_head) [*标识符字符集*](..\chapter3\02_Lexical_Structure.html#identifier_characters) _可选_
> *标识符* → [*隐式参数名*](..\chapter3\02_Lexical_Structure.html#implicit_parameter_name)
-> *标识符列表* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) **,** [*标识符列表*](..\chapter3\02_Lexical_Structure.html#identifier_list)
-> *标识符头(Head)* → Upper- or lowercase letter A through Z
+> *标识符集* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) | [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier) **,** [*标识符集*](..\chapter3\02_Lexical_Structure.html#identifier_list)
+> *标识符头(Head)* → Upper- or lowercase letter A through Z
+
+> *标识符头(Head)* → _
+
> *标识符头(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
@@ -610,13 +739,19 @@ _________________
> *标识符字符* → 数值 0 到 9
> *标识符字符* → U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+FE2F
> *标识符字符* → [*标识符头(Head)*](..\chapter3\02_Lexical_Structure.html#identifier_head)
-> *标识符字符列表* → [*标识符字符*](..\chapter3\02_Lexical_Structure.html#identifier_character) [*标识符字符列表*](..\chapter3\02_Lexical_Structure.html#identifier_characters) _可选_
-> *隐式参数名* → **$** [*十进制数字列表*](..\chapter3\02_Lexical_Structure.html#decimal_digits)
+> *标识符字符集* → [*标识符字符*](..\chapter3\02_Lexical_Structure.html#identifier_character) [*标识符字符集*](..\chapter3\02_Lexical_Structure.html#identifier_characters) _可选_
+> *隐式参数名* → **$** [*十进制数字集*](..\chapter3\02_Lexical_Structure.html#decimal_digits)
> 字面量语法
-> *字面量* → [*整型字面量*](..\chapter3\02_Lexical_Structure.html#integer_literal) | [*浮点数字面量*](..\chapter3\02_Lexical_Structure.html#floating_point_literal) | [*字符串字面量*](..\chapter3\02_Lexical_Structure.html#string_literal)
+> *字面量* → [*数值型字面量*](..\chapter3\02_Lexical_Structure.html#integer_literal) | [*字符串字面量*](..\chapter3\02_Lexical_Structure.html#floating_point_literal) | [*布尔字面量*](..\chapter3\02_Lexical_Structure.html#string_literal) | [*空字面量*](TODO)
+
+> *数值型字面量* → **-** _可选_ [*整形字面量*](TODO) | **-** _可选_ [*浮点型字面量*](TODO)
+
+> *布尔字面量* → **true** | **false**
+
+> *空字面量* → **nil**
@@ -625,23 +760,23 @@ _________________
> *整型字面量* → [*八进制字面量*](..\chapter3\02_Lexical_Structure.html#octal_literal)
> *整型字面量* → [*十进制字面量*](..\chapter3\02_Lexical_Structure.html#decimal_literal)
> *整型字面量* → [*十六进制字面量*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal)
-> *二进制字面量* → **0b** [*二进制数字*](..\chapter3\02_Lexical_Structure.html#binary_digit) [*二进制字面量字符列表*](..\chapter3\02_Lexical_Structure.html#binary_literal_characters) _可选_
+> *二进制字面量* → **0b** [*二进制数字*](..\chapter3\02_Lexical_Structure.html#binary_digit) [*二进制字面量字符集*](..\chapter3\02_Lexical_Structure.html#binary_literal_characters) _可选_
> *二进制数字* → 数值 0 到 1
> *二进制字面量字符* → [*二进制数字*](..\chapter3\02_Lexical_Structure.html#binary_digit) | **_**
-> *二进制字面量字符列表* → [*二进制字面量字符*](..\chapter3\02_Lexical_Structure.html#binary_literal_character) [*二进制字面量字符列表*](..\chapter3\02_Lexical_Structure.html#binary_literal_characters) _可选_
-> *八进制字面量* → **0o** [*八进字数字*](..\chapter3\02_Lexical_Structure.html#octal_digit) [*八进制字符列表*](..\chapter3\02_Lexical_Structure.html#octal_literal_characters) _可选_
+> *二进制字面量字符集* → [*二进制字面量字符*](..\chapter3\02_Lexical_Structure.html#binary_literal_character) [*二进制字面量字符集*](..\chapter3\02_Lexical_Structure.html#binary_literal_characters) _可选_
+> *八进制字面量* → **0o** [*八进制数字*](..\chapter3\02_Lexical_Structure.html#octal_digit) [*八进制字符集*](..\chapter3\02_Lexical_Structure.html#octal_literal_characters) _可选_
> *八进字数字* → 数值 0 到 7
-> *八进制字符* → [*八进字数字*](..\chapter3\02_Lexical_Structure.html#octal_digit) | **_**
-> *八进制字符列表* → [*八进制字符*](..\chapter3\02_Lexical_Structure.html#octal_literal_character) [*八进制字符列表*](..\chapter3\02_Lexical_Structure.html#octal_literal_characters) _可选_
-> *十进制字面量* → [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) [*十进制字符列表*](..\chapter3\02_Lexical_Structure.html#decimal_literal_characters) _可选_
+> *八进制字符* → [*八进制数字*](..\chapter3\02_Lexical_Structure.html#octal_digit) | **_**
+> *八进制字符集* → [*八进制字符*](..\chapter3\02_Lexical_Structure.html#octal_literal_character) [*八进制字符集*](..\chapter3\02_Lexical_Structure.html#octal_literal_characters) _可选_
+> *十进制字面量* → [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) [*十进制字符集*](..\chapter3\02_Lexical_Structure.html#decimal_literal_characters) _可选_
> *十进制数字* → 数值 0 到 9
-> *十进制数字列表* → [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) [*十进制数字列表*](..\chapter3\02_Lexical_Structure.html#decimal_digits) _可选_
-> *十进制字符* → [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) | **_**
-> *十进制字符列表* → [*十进制字符*](..\chapter3\02_Lexical_Structure.html#decimal_literal_character) [*十进制字符列表*](..\chapter3\02_Lexical_Structure.html#decimal_literal_characters) _可选_
-> *十六进制字面量* → **0x** [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制字面量字符列表*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal_characters) _可选_
+> *十进制数字集* → [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) [*十进制数字集*](..\chapter3\02_Lexical_Structure.html#decimal_digits) _可选_
+> *十进制字面量字符* → [*十进制数字*](..\chapter3\02_Lexical_Structure.html#decimal_digit) | **_**
+> *十进制字面量字符集* → [*十进制字面量字符*](..\chapter3\02_Lexical_Structure.html#decimal_literal_character) [*十进制字面量字符集*](..\chapter3\02_Lexical_Structure.html#decimal_literal_characters) _可选_
+> *十六进制字面量* → **0x** [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制字面量字符集*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal_characters) _可选_
> *十六进制数字* → 数值 0 到 9, a through f, or A through F
> *十六进制字符* → [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) | **_**
-> *十六进制字面量字符列表* → [*十六进制字符*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal_character) [*十六进制字面量字符列表*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal_characters) _可选_
+> *十六进制字面量字符集* → [*十六进制字符*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal_character) [*十六进制字面量字符集*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal_characters) _可选_
@@ -650,7 +785,8 @@ _________________
> *浮点数字面量* → [*十六进制字面量*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal) [*十六进制分数*](..\chapter3\02_Lexical_Structure.html#hexadecimal_fraction) _可选_ [*十六进制指数*](..\chapter3\02_Lexical_Structure.html#hexadecimal_exponent)
> *十进制分数* → **.** [*十进制字面量*](..\chapter3\02_Lexical_Structure.html#decimal_literal)
> *十进制指数* → [*浮点数e*](..\chapter3\02_Lexical_Structure.html#floating_point_e) [*正负号*](..\chapter3\02_Lexical_Structure.html#sign) _可选_ [*十进制字面量*](..\chapter3\02_Lexical_Structure.html#decimal_literal)
-> *十六进制分数* → **.** [*十六进制字面量*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal) _可选_
+> *十六进制分数* → **.** [*十六进制数*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal)
+ [*十六进制字面量字符集*](TODO)_可选_
> *十六进制指数* → [*浮点数p*](..\chapter3\02_Lexical_Structure.html#floating_point_p) [*正负号*](..\chapter3\02_Lexical_Structure.html#sign) _可选_ [*十六进制字面量*](..\chapter3\02_Lexical_Structure.html#hexadecimal_literal)
> *浮点数e* → **e** | **E**
> *浮点数p* → **p** | **P**
@@ -658,22 +794,72 @@ _________________
-> 字符型字面量语法
+> 字符串型字面量语法
> *字符串字面量* → **"** [*引用文本*](..\chapter3\02_Lexical_Structure.html#quoted_text) **"**
> *引用文本* → [*引用文本条目*](..\chapter3\02_Lexical_Structure.html#quoted_text_item) [*引用文本*](..\chapter3\02_Lexical_Structure.html#quoted_text) _可选_
> *引用文本条目* → [*转义字符*](..\chapter3\02_Lexical_Structure.html#escaped_character)
-> *引用文本条目* → **\(** [*表达式*](..\chapter3\04_Expressions.html#expression) **)**
+> *引用文本条目* → **(** [*表达式*](..\chapter3\04_Expressions.html#expression) **)**
> *引用文本条目* → 除了", \, U+000A, or U+000D的所有Unicode的字符
> *转义字符* → **\0** | **\\** | **\t** | **\n** | **\r** | **\"** | **\'**
-> *转义字符* → **\x** [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit)
-> *转义字符* → **\u** [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit)
-> *转义字符* → **\U** [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit) [*十六进制数字*](..\chapter3\02_Lexical_Structure.html#hexadecimal_digit)
+> *转义字符* → **\u** **{** [*十六进制标量数字集*](TODO) **}**
+> *unicode标量数字集* → Between one and eight hexadecimal digits
> 运算符语法语法
-> *运算符* → [*运算符字符*](..\chapter3\02_Lexical_Structure.html#operator_character) [*运算符*](..\chapter3\02_Lexical_Structure.html#operator) _可选_
-> *运算符字符* → **/** | **=** | **-** | **+** | **!** | ***** | **%** | **<** | **>** | **&** | **|** | **^** | **~** | **.**
+> *运算符* → [*运算符头*](..\chapter3\02_Lexical_Structure.html#operator_character) [*运算符字符集*](..\chapter3\02_Lexical_Structure.html#operator) _可选_
+> *运算符* → [*点运算符头*](TODO) [*点运算符字符集*](TODO) _可选_
+> *运算符字符* → **/** | **=** | **-** | **+** | **!** | ***** | **%** | **<** | **>** | **&** | **|** | **^** | **~** | **?**
+> *运算符头* → 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
+
+> *运算符字符* → [*运算符头*](TODO)
+
+> *运算符字符* → U+0300–U+036F
+
+> *运算符字符* → U+1DC0–U+1DFF
+
+> *运算符字符* → U+20D0–U+20FF
+
+> *运算符字符* → U+FE00–U+FE0F
+
+> *运算符字符* → U+FE20–U+FE2F
+
+> *运算符字符* → U+E0100–U+E01EF
+
+> *运算符字符集* → [*运算符字符*](TODO) [*运算符字符集*](TODO)_可选_
+
+> *点运算符头* → **..**
+
+> *点运算符字符* → **.** | [*运算符字符*](TODO)
+
+> *点运算符字符集* → [*点运算符字符*](TODO) [*点运算符字符集*](TODO) _可选_
+
> *二元运算符* → [*运算符*](..\chapter3\02_Lexical_Structure.html#operator)
> *前置运算符* → [*运算符*](..\chapter3\02_Lexical_Structure.html#operator)
> *后置运算符* → [*运算符*](..\chapter3\02_Lexical_Structure.html#operator)
@@ -682,37 +868,42 @@ _________________
## 类型
> 类型语法
-> *类型* → [*数组类型*](..\chapter3\03_Types.html#array_type) | [*函数类型*](..\chapter3\03_Types.html#function_type) | [*类型标识*](..\chapter3\03_Types.html#type_identifier) | [*元组类型*](..\chapter3\03_Types.html#tuple_type) | [*可选类型*](..\chapter3\03_Types.html#optional_type) | [*隐式解析可选类型*](..\chapter3\03_Types.html#implicitly_unwrapped_optional_type) | [*协议合成类型*](..\chapter3\03_Types.html#protocol_composition_type) | [*元型类型*](..\chapter3\03_Types.html#metatype_type)
+> *类型* → [*数组类型*](..\chapter3\03_Types.html#array_type) | [*字典类型*](TODO) | [*函数类型*](..\chapter3\03_Types.html#function_type) | [*类型标识符*](..\chapter3\03_Types.html#type_identifier) | [*元组类型*](..\chapter3\03_Types.html#tuple_type) | [*可选类型*](..\chapter3\03_Types.html#optional_type) | [*隐式解析可选类型*](..\chapter3\03_Types.html#implicitly_unwrapped_optional_type) | [*协议合成类型*](..\chapter3\03_Types.html#protocol_composition_type) | [*元型类型*](..\chapter3\03_Types.html#metatype_type)
> 类型注解语法
-> *类型注解* → **:** [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type)
+> *类型注解* → **:** [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ [*类型*](..\chapter3\03_Types.html#type)
> 类型标识语法
-> *类型标识* → [*类型名称*](..\chapter3\03_Types.html#type_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ | [*类型名称*](..\chapter3\03_Types.html#type_name) [*泛型参数子句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ **.** [*类型标识*](..\chapter3\03_Types.html#type_identifier)
-> *类名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
+> *类型标识* → [*类型名称*](..\chapter3\03_Types.html#type_name) [*泛型参数从句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ | [*类型名称*](..\chapter3\03_Types.html#type_name) [*泛型参数从句*](GenericParametersAndArguments.html#generic_argument_clause) _可选_ **.** [*类型标识符*](..\chapter3\03_Types.html#type_identifier)
+> *类型名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
> 元组类型语法
> *元组类型* → **(** [*元组类型主体*](..\chapter3\03_Types.html#tuple_type_body) _可选_ **)**
-> *元组类型主体* → [*元组类型的元素列表*](..\chapter3\03_Types.html#tuple_type_element_list) **...** _可选_
-> *元组类型的元素列表* → [*元组类型的元素*](..\chapter3\03_Types.html#tuple_type_element) | [*元组类型的元素*](..\chapter3\03_Types.html#tuple_type_element) **,** [*元组类型的元素列表*](..\chapter3\03_Types.html#tuple_type_element_list)
-> *元组类型的元素* → [*特性(Attributes)列表*](..\chapter3\06_Attributes.html#attributes) _可选_ **inout** _可选_ [*类型*](..\chapter3\03_Types.html#type) | **inout** _可选_ [*元素名*](..\chapter3\03_Types.html#element_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation)
+> *元组类型主体* → [*元组类型的元素集*](..\chapter3\03_Types.html#tuple_type_element_list) **...** _可选_
+> *元组类型的元素集* → [*元组类型的元素*](..\chapter3\03_Types.html#tuple_type_element) | [*元组类型的元素*](..\chapter3\03_Types.html#tuple_type_element) **,** [*元组类型的元素集*](..\chapter3\03_Types.html#tuple_type_element_list)
+> *元组类型的元素* → [*属性(Attributes)集*](..\chapter3\06_Attributes.html#attributes) _可选_ **inout** _可选_ [*类型*](..\chapter3\03_Types.html#type) | **inout** _可选_ [*元素名*](..\chapter3\03_Types.html#element_name) [*类型注解*](..\chapter3\03_Types.html#type_annotation)
> *元素名* → [*标识符*](..\chapter3\02_Lexical_Structure.html#identifier)
> 函数类型语法
-> *函数类型* → [*类型*](..\chapter3\03_Types.html#type) **->** [*类型*](..\chapter3\03_Types.html#type)
+> *函数类型* → [*类型*](..\chapter3\03_Types.html#type) **throws** _可选_ **->** [*类型*](..\chapter3\03_Types.html#type)
+> *函数类型* → [*类型*](TODO) **rethrows** **->** [*类型*](TODO)
> 数组类型语法
-> *数组类型* → [*类型*](..\chapter3\03_Types.html#type) **[** **]** | [*数组类型*](..\chapter3\03_Types.html#array_type) **[** **]**
+> *数组类型* → **[** [*类型*](..\chapter3\03_Types.html#array_type) **]**
+
+
+> 字典类型语法
+> *字典类型* → **[** [*类型 **:** 类型*](TODO) **]**
@@ -727,9 +918,9 @@ _________________
> 协议合成类型语法
-> *协议合成类型* → **protocol** **<** [*协议标识符列表*](..\chapter3\03_Types.html#protocol_identifier_list) _可选_ **>**
-> *协议标识符列表* → [*协议标识符*](..\chapter3\03_Types.html#protocol_identifier) | [*协议标识符*](..\chapter3\03_Types.html#protocol_identifier) **,** [*协议标识符列表*](..\chapter3\03_Types.html#protocol_identifier_list)
-> *协议标识符* → [*类型标识*](..\chapter3\03_Types.html#type_identifier)
+> *协议合成类型* → **protocol** **<** [*协议标识符集*](..\chapter3\03_Types.html#protocol_identifier_list) _可选_ **>**
+> *协议标识符集* → [*协议标识符*](..\chapter3\03_Types.html#protocol_identifier) | [*协议标识符*](..\chapter3\03_Types.html#protocol_identifier) **,** [*协议标识符集*](..\chapter3\03_Types.html#protocol_identifier_list)
+> *协议标识符* → [*类型标识符*](..\chapter3\03_Types.html#type_identifier)
@@ -738,6 +929,14 @@ _________________
-> 类型继承子句语法
-> *类型继承子句* → **:** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list)
-> *类型继承列表* → [*类型标识*](..\chapter3\03_Types.html#type_identifier) | [*类型标识*](..\chapter3\03_Types.html#type_identifier) **,** [*类型继承列表*](..\chapter3\03_Types.html#type_inheritance_list)
+> 类型继承从句语法
+
+> *类型继承从句* → **:** [*类条件(class-requirement))*](TODO) **,** [*类型继承集*](..\chapter3\03_Types.html#type_inheritance_list)
+
+> *类型继承从句* → **:** [*类条件(class-requirement))*](TODO)
+
+> *类型继承从句* → **:** [*类型继承集*](TODO)
+
+> *类型继承集* → [*类型标识符*](..\chapter3\03_Types.html#type_identifier) | [*类型标识符*](..\chapter3\03_Types.html#type_identifier) **,** [*类型继承集*](..\chapter3\03_Types.html#type_inheritance_list)
+
+> *类条件* → **class**
From c1d845819ebbaab72d98eb980b3ac905dd294170 Mon Sep 17 00:00:00 2001
From: DianQK
Date: Sun, 5 Jul 2015 15:59:10 +0800
Subject: [PATCH 080/228] update String and Characters
---
source/chapter2/03_Strings_and_Characters.md | 826 ++++++++++++-------
1 file changed, 540 insertions(+), 286 deletions(-)
diff --git a/source/chapter2/03_Strings_and_Characters.md b/source/chapter2/03_Strings_and_Characters.md
index 0a3edf6c..13d5dd3d 100755
--- a/source/chapter2/03_Strings_and_Characters.md
+++ b/source/chapter2/03_Strings_and_Characters.md
@@ -2,89 +2,67 @@
> 校对:[Hawstein](https://github.com/Hawstein)
# 字符串和字符(Strings and Characters)
------------------
+---
本页包含内容:
-- [字符串字面量](#string_literals)
-- [初始化空字符串](#initializing_an_empty_string)
-- [字符串可变性](#string_mutability)
-- [字符串是值类型](#strings_are_value_types)
-- [使用字符](#working_with_characters)
-- [计算字符数量](#counting_characters)
-- [连接字符串和字符](#concatenating_strings_and_characters)
-- [字符串插值](#string_interpolation)
-- [比较字符串](#comparing_strings)
-- [字符串大小写](#uppercase_and_lowercase_strings)
-- [Unicode](#unicode)
+- [字符串字面量](#string_literals)
+- [初始化空字符串](#initializing_an_empty_string)
+- [字符串可变性](#string_mutability)
+- [字符串是值类型](#strings_are_value_types)
+- [使用字符](#working_with_characters)
+- [连接字符串和字符](#concatenating_strings_and_characters)
+- [字符串插值](#string_interpolation)
+- [Unicode](#unicode)
+- [计算字符数量](#counting_characters)
+- [访问和修改字符串](#accessing_and_modifying_a_string)
+- [比较字符串](#comparing_strings)
+- [字符串的 Unicode 表示形式](#unicode_representations_of_strings)
-`String`是例如"hello, world","海贼王"这样的有序的`Character`(字符)类型的值的集合,通过`String`类型来表示。
-Swift 的`String`和`Character`类型提供了一个快速的,兼容 Unicode 的方式来处理代码中的文本信息。
-创建和操作字符串的语法与 C 语言中字符串操作相似,轻量并且易读。
-字符串连接操作只需要简单地通过`+`号将两个字符串相连即可。
+`String`是例如"hello, world","albatross"这样的有序的`Character`(字符)类型的值的集合,通过`String`类型来表示。
+Swift 的`String`和`Character`类型提供了一个快速的,兼容 Unicode 的方式来处理代码中的文本。
+创建和操作字符串的语法与 C 语言中字符串操作相似,轻量并且易读。
+字符串连接操作只需要简单地通过`+`符号将两个字符串相连即可。
与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。
+尽管语法简易,但`String`类型是一种快速、现代化的字符串实现。
+每一个字符串都是由编码无关的 Unicode 字符组成,并支持访问字符的多种 Unicode 表示形式(representations)。
+你也可以在常量、变量、字面量和表达式中进行字符串插值操作,这可以帮助你轻松创建用于展示、存储和打印的自定义字符串。
-尽管语法简易,但`String`类型是一种快速、现代化的字符串实现。
-每一个字符串都是由独立编码的 Unicode 字符组成,并提供了以不同 Unicode 表示(representations)来访问这些字符的支持。
-
-Swift 可以在常量、变量、字面量和表达式中进行字符串插值操作,可以轻松创建用于展示、存储和打印的自定义字符串。
-
-> 注意:
-Swift 的`String`类型与 Foundation `NSString`类进行了无缝桥接。如果您利用 Cocoa 或 Cocoa Touch 中的 Foundation 框架进行工作。所有`NSString` API 都可以调用您创建的任意`String`类型的值。除此之外,还可以使用本章介绍的`String`特性。您也可以在任意要求传入`NSString`实例作为参数的 API 中使用`String`类型的值作为替代。
->更多关于在 Foundation 和 Cocoa 中使用`String`的信息请查看 [Using Swift with Cocoa and Objective-C](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)。
+> 注意:
+> Swift 的`String`类型与 Foundation `NSString`类进行了无缝桥接。就像 [AnyObject](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html#//apple_ref/doc/uid/TP40014097-CH22-ID343) 中提到的一样,在使用 Cocoa 中的 Foundation 框架时,您可以将创建的任何字符串的值转换成`NSString`,并调用任意的`NSString` API。您也可以在任意要求传入`NSString`实例作为参数的 API 中用`String`类型的值代替。
+> 更多关于在 Foundation 和 Cocoa 中使用`String`的信息请查看 *[Using Swift with Cocoa and Objective-C](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)*。
+
+
## 字符串字面量(String Literals)
-您可以在您的代码中包含一段预定义的字符串值作为字符串字面量。
-字符串字面量是由双引号 ("") 包裹着的具有固定顺序的文本字符集。
-
-字符串字面量可以用于为常量和变量提供初始值。
-
-```swift
-let someString = "Some string literal value"
-```
-
-> 注意:
-`someString`常量通过字符串字面量进行初始化,Swift 因此推断该常量为`String`类型。
-
-字符串字面量可以包含以下特殊字符:
-
-* 转义字符`\0`(空字符)、`\\`(反斜线)、`\t`(水平制表符)、`\n`(换行符)、`\r`(回车符)、`\"`(双引号)、`\'`(单引号)。
-* Unicode 标量,写成`\u{n}`(u为小写),其中`n`为任意的一到八位十六进制数。
-
-下面的代码为各种特殊字符的使用示例。
-`wiseWords`常量包含了两个转移特殊字符 (双括号);
-`dollarSign`、`blackHeart`和`sparklingHeart`常量演示了三种不同格式的 Unicode 标量:
-
-```swift
-let wiseWords = "\"我是要成为海贼王的男人\" - 路飞"
-// "我是要成为海贼王的男人" - 路飞
-let dollarSign = "\u{24}" // $, Unicode 标量 U+0024
-let blackHeart = "\u{2665}" // ♥, Unicode 标量 U+2665
-let sparklingHeart = "\u{1F496}" // 💖, Unicode 标量 U+1F496
-```
+您可以在您的代码中包含一段预定义的字符串值作为字符串字面量。字符串字面量是由双引号 ("") 包裹着的具有固定顺序的文本字符集。
+字符串字面量可以用于为常量和变量提供初始值:
+```let someString = "Some string literal value"```
+注意`someString`常量通过字符串字面量进行初始化,Swift 会推断该常量为`String`类型。
+> 注意:
+> 更多关于在字面量的特殊字符,请查看 [Special Characters in String Literals](#special_characters_in_string_literals) 。
+
## 初始化空字符串 (Initializing an Empty String)
-为了构造一个很长的字符串,可以创建一个空字符串作为初始值。
-可以将空的字符串字面量赋值给变量,也可以初始化一个新的`String`实例:
-
-```swift
-var emptyString = "" // 空字符串字面量
-var anotherEmptyString = String() // 初始化 String 实例
-// 两个字符串均为空并等价。
+要创建一个空字符串作为初始值,可以将空的字符串字面量赋值给变量,也可以初始化一个新的`String`实例:
+
+```
+var emptyString = "" // 空字符串字面量
+var anotherEmptyString = String() // 初始化方法
+// 两个字符串均为空并等价。
```
-您可以通过检查其`Boolean`类型的`isEmpty`属性来判断该字符串是否为空:
-
-```swift
-if emptyString.isEmpty {
- println("什么都没有")
-}
-// 打印输出:"什么都没有"
+您可以通过检查其`Boolean`类型的`isEmpty`属性来判断该字符串是否为空:
+```
+if emptyString.isEmpty {
+ print("Nothing to see here")
+}
+// 打印输出:"Nothing to see here"
```
@@ -92,28 +70,28 @@ if emptyString.isEmpty {
您可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改:
-```swift
-var variableString = "Horse"
-variableString += " and carriage"
-// variableString 现在为 "Horse and carriage"
-let constantString = "Highlander"
-constantString += " and another Highlander"
-// 这会报告一个编译错误 (compile-time error) - 常量不可以被修改。
+```
+var variableString = "Horse"
+variableString += " and carriage"
+// variableString 现在为 "Horse and carriage"
+let constantString = "Highlander"
+constantString += " and another Highlander"
+// 这会报告一个编译错误 (compile-time error) - 常量不可以被修改。
```
-> 注意:
-在 Objective-C 和 Cocoa 中,您通过选择两个不同的类(`NSString`和`NSMutableString`)来指定该字符串是否可以被修改,Swift 中的字符串是否可以修改仅通过定义的是变量还是常量来决定,实现了多种类型可变性操作的统一。
+> 注意:
+> 在 Objective-C 和 Cocoa 中,您需要通过选择两个不同的类(`NSString`和`NSMutableString`)来指定该字符串是否可以被修改。
## 字符串是值类型(Strings Are Value Types)
-Swift 的`String`类型是值类型。
-如果您创建了一个新的字符串,那么当其进行常量、变量赋值操作或在函数/方法中传递时,会进行值拷贝。
+Swift 的`String`类型是值类型。
+如果您创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。
任何情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值操作。
-值类型在 [结构体和枚举是值类型](09_Classes_and_Structures.html#structures_and_enumerations_are_value_types) 中进行了说明。
+值类型在 [结构体和枚举是值类型](09_Classes_and_Structures.html#structures_and_enumerations_are_value_types) 中进行了详细描述。
-> 注意:
-与 Cocoa 中的`NSString`不同,当您在 Cocoa 中创建了一个`NSString`实例,并将其传递给一个函数/方法,或者赋值给一个变量,您传递或赋值的是该`NSString`实例的一个引用,除非您特别要求进行值拷贝,否则字符串不会生成新的副本来进行赋值操作。
+> 注意:
+> 与 Cocoa 中的`NSString`不同,当您在 Cocoa 中创建了一个`NSString`实例,并将其传递给一个函数/方法,或者赋值给一个变量,您传递或赋值的是该`NSString`实例的一个引用,除非您特别要求进行值拷贝,否则字符串不会生成新的副本来进行赋值操作。
Swift 默认字符串拷贝的方式保证了在函数/方法中传递的是字符串的值。
很明显无论该值来自于哪里,都是您独自拥有的。
@@ -124,85 +102,77 @@ Swift 默认字符串拷贝的方式保证了在函数/方法中传递的是字
## 使用字符(Working with Characters)
-Swift 的`String`类型表示特定序列的`Character`(字符) 类型值的集合。
-每一个字符值代表一个 Unicode 字符。
-您可利用`for-in`循环来遍历字符串中的每一个字符:
+您可通过`for-in`循环来遍历字符串中的`characters`属性来获取每一个字符的值:
-```swift
-for character in "Dog!🐶" {
- println(character)
-}
-// D
-// o
-// g
-// !
-// 🐶
+```
+for character in "Dog!🐶".characters {
+ print(character)
+}
+// D
+// o
+// g
+// !
+// 🐶
```
for-in 循环在 [For Loops](05_Control_Flow.html#for_loops) 中进行了详细描述。
-另外,通过标明一个`Character`类型注解并通过字符字面量进行赋值,可以建立一个独立的字符常量或变量:
-
-```swift
-let yenSign: Character = "¥"
-```
-
-
-## 计算字符数量 (Counting Characters)
-
-通过调用全局`count(_:)`函数,并将字符串作为参数进行传递,可以获取该字符串的字符数量。
-
-```swift
-let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
-println("unusualMenagerie has \(count(unusualMenagerie)) characters")
-// 打印输出:"unusualMenagerie has 40 characters"
-```
-
-> 注意:
-不同的 Unicode 字符以及相同 Unicode 字符的不同表示方式可能需要不同数量的内存空间来存储。所以 Swift 中的字符在一个字符串中并不一定占用相同的内存空间。因此字符串的长度不得不通过迭代字符串中每一个字符的长度来进行计算。如果您正在处理一个长字符串,需要注意`countElements`函数必须遍历字符串中的字符以精准计算字符串的长度。
-> 另外需要注意的是通过`countElements`返回的字符数量并不总是与包含相同字符的`NSString`的`length`属性相同。`NSString`的`length`属性是基于利用 UTF-16 表示的十六位代码单元数字,而不是基于 Unicode 字符。为了解决这个问题,`NSString`的`length`属性在被 Swift 的`String`访问时会成为`utf16count`。
+另外,通过标明一个`Character`类型并用字符字面量进行赋值,可以建立一个独立的字符常量或变量:
+```
+let exclamationMark: Charater = "!"
+```
+字符串可以通过传递一个值类型为`Charater`的数组作为自变量来初始化:
+
+```
+let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
+let catString = String(catCharacters)
+print(catString)
+// 打印输出:"Cat!🐱"
+```
+
## 连接字符串和字符 (Concatenating Strings and Characters)
-字符串可以通过加法运算符(`+`)相加在一起(或称“串联”)并创建一个新的字符串:
+字符串可以通过加法运算符(`+`)相加在一起(或称“连接”)创建一个新的字符串:
-```swift
-let string1 = "hello"
-let string2 = " there"
-var welcome = string1 + string2
-// welcome 现在等于 "hello there"
+```
+let string1 = "hello"
+let string2 = " there"
+var welcome = string1 + string2
+// welcome 现在等于 "hello there"
```
您也可以通过加法赋值运算符 (`+=`) 将一个字符串添加到一个已经存在字符串变量上:
-```swift
-var instruction = "look over"
-instruction += string2
-// instruction 现在等于 "look over there"
+```
+var instruction = "look over"
+instruction += string2
+// instruction 现在等于 "look over there"
+```
-```
-你可以用将`append`方法将一个字符附加到一个字符串变量的尾部:
+您可以用`append`方法将一个字符附加到一个字符串变量的尾部:
-```swift
-let exclamationMark: Character = "!"
-welcome.append(exclamationMark)
-// welcome 现在等于 "hello there!"
+```
+let exclamationMark: Character = "!"
+welcome.append(exclamationMark)
+// welcome 现在等于 "hello there!"
```
-> 注意:
-您不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。
-
+> 注意:
+> 您不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。
+
+
## 字符串插值 (String Interpolation)
字符串插值是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式。
-您插入的字符串字面量的每一项都被包裹在以反斜线为前缀的圆括号中:
+您插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中:
-```swift
-let multiplier = 3
-let message = "\(multiplier) 乘以 2.5 是 \(Double(multiplier) * 2.5)"
-// message 是 "3 乘以 2.5 是 7.5"
+```
+let multiplier = 3
+let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
+// message 是 "3 times 2.5 is 7.5"
```
在上面的例子中,`multiplier`作为`\(multiplier)`被插入到一个字符串字面量中。
@@ -212,199 +182,483 @@ let message = "\(multiplier) 乘以 2.5 是 \(Double(multiplier) * 2.5)"
该表达式计算`Double(multiplier) * 2.5`的值并将结果 (7.5) 插入到字符串中。
在这个例子中,表达式写为`\(Double(multiplier) * 2.5)`并包含在字符串字面量中。
-> 注意:
-插值字符串中写在括号中的表达式不能包含非转义双引号 (`"`) 和反斜杠 (`\`),并且不能包含回车或换行符。
+> 注意:
+> 插值字符串中写在括号中的表达式不能包含非转义双引号 (`"`) 和反斜杠 (`\`),并且不能包含回车或换行符。
+
-
-## 比较字符串 (Comparing Strings)
-
-Swift 提供了三种方式来比较字符串的值:字符串相等、前缀相等和后缀相等。
-
-
-### 字符串相等 (String Equality)
-
-如果两个字符串以同一顺序包含完全相同的字符,则认为两者字符串相等:
-
-```swift
-let quotation = "我们是一样一样滴."
-let sameQuotation = "我们是一样一样滴."
-if quotation == sameQuotation {
- println("这两个字符串被认为是相同的")
-}
-// 打印输出:"这两个字符串被认为是相同的"
-```
-
-
-### 前缀/后缀相等 (Prefix and Suffix Equality)
-
-通过调用字符串的`hasPrefix`/`hasSuffix`方法来检查字符串是否拥有特定前缀/后缀。
-两个方法均需要以字符串作为参数传入并传出`Boolean`值。
-两个方法均执行基本字符串和前缀/后缀字符串之间逐个字符的比较操作。
-
-下面的例子以一个字符串数组表示莎士比亚话剧《罗密欧与朱丽叶》中前两场的场景位置:
-
-```swift
-let romeoAndJuliet = [
- "Act 1 Scene 1: Verona, A public place",
- "Act 1 Scene 2: Capulet's mansion",
- "Act 1 Scene 3: A room in Capulet's mansion",
- "Act 1 Scene 4: A street outside Capulet's mansion",
- "Act 1 Scene 5: The Great Hall in Capulet's mansion",
- "Act 2 Scene 1: Outside Capulet's mansion",
- "Act 2 Scene 2: Capulet's orchard",
- "Act 2 Scene 3: Outside Friar Lawrence's cell",
- "Act 2 Scene 4: A street in Verona",
- "Act 2 Scene 5: Capulet's mansion",
- "Act 2 Scene 6: Friar Lawrence's cell"
-]
-```
-
-您可以利用`hasPrefix`方法来计算话剧中第一幕的场景数:
-
-```swift
-var act1SceneCount = 0
-for scene in romeoAndJuliet {
- if scene.hasPrefix("Act 1 ") {
- ++act1SceneCount
- }
-}
-println("There are \(act1SceneCount) scenes in Act 1")
-// 打印输出:"There are 5 scenes in Act 1"
-```
-
-相似地,您可以用`hasSuffix`方法来计算发生在不同地方的场景数:
-
-```swift
-var mansionCount = 0
-var cellCount = 0
-for scene in romeoAndJuliet {
- if scene.hasSuffix("Capulet's mansion") {
- ++mansionCount
- } else if scene.hasSuffix("Friar Lawrence's cell") {
- ++cellCount
- }
-}
-println("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
-// 打印输出:"6 mansion scenes; 2 cell scenes"
-```
-
-
-### 大写和小写字符串(Uppercase and Lowercase Strings)
-
-您可以通过字符串的`uppercaseString`和`lowercaseString`属性来访问大写/小写版本的字符串。
-
-```swift
-import Foundation
-
-let normal = "Could you help me, please?"
-let shouty = normal.uppercaseString
-// shouty 值为 "COULD YOU HELP ME, PLEASE?"
-let whispered = normal.lowercaseString
-// whispered 值为 "could you help me, please?"
-```
-
-
+
## Unicode
Unicode 是一个国际标准,用于文本的编码和表示。
它使您可以用标准格式表示来自任意语言几乎所有的字符,并能够对文本文件或网页这样的外部资源中的字符进行读写操作。
+Swift 的字符串和字符类型是完全兼容 Unicode 标准的。
+
+
+### Unicode 标量(Unicode Scalars)
-Swift 的字符串和字符类型是完全兼容 Unicode 标准的,它支持如下所述的一系列不同的 Unicode 编码。
+Swift 的`String`类型是基于 *Unicode 标量* 建立的。
+Unicode 标量是对应字符的唯一21位数字或者修饰符,例如`U+0061`表示小写的拉丁字母(`LATIN SMALL LETTER A`)("`a`"),`U+1F425`表示小鸡表情(`FRONT-FACING BABY CHICK`) ("`🐥`")
+> 注意:
+> Unicode *码位(code poing)* 的范围是`U+0000`到`U+D7FF`或者`U+E000`到`U+10FFFF`。Unicode 标量不包括 Unicode *代理项(surrogate pair)* 码位,其码位范围是`U+D800`到`U+DFFF`。
+
+注意不是所有的21位 Unicode 标量都代表一个字符,因为有一些标量是保留给未来分配的。已经代表一个典型字符的标量都有自己的名字,例如上面例子中的`LATIN SMALL LETTER A`和`FRONT-FACING BABY CHICK`。
+
+
+### 字符串字面量的特殊字符 (Special Characters in String Literals)
-
-### Unicode 术语(Unicode Terminology)
+字符串字面量可以包含以下特殊字符:
-Unicode 中每一个字符都可以被解释为一个或多个 unicode 标量。
-字符的 unicode 标量是一个唯一的21位数字(和名称),例如`U+0061`表示小写的拉丁字母A ("a"),`U+1F425`表示小鸡表情 ("🐥")
+* 转义字符`\0`(空字符)、`\\`(反斜线)、`\t`(水平制表符)、`\n`(换行符)、`\r`(回车符)、`\"`(双引号)、`\'`(单引号)。
+* Unicode 标量,写成`\u{n}`(u为小写),其中`n`为任意一到八位十六进制数且可用的 Unicode 位码。
-当 Unicode 字符串被写进文本文件或其他存储结构当中,这些 unicode 标量将会按照 Unicode 定义的集中格式之一进行编码。其包括`UTF-8`(以8位代码单元进行编码) 和`UTF-16`(以16位代码单元进行编码)。
+下面的代码为各种特殊字符的使用示例。
+`wiseWords`常量包含了两个双引号;
+`dollarSign`、`blackHeart`和`sparklingHeart`常量演示了三种不同格式的 Unicode 标量:
+
+```
+let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
+// "Imageination is more important than knowledge" - Enistein
+let dollarSign = "\u{24}" // $, Unicode 标量 U+0024
+let blackHeart = "\u{2665}" // ♥, Unicode 标量 U+2665
+let sparklingHeart = "\u{1F496}" // 💖, Unicode 标量 U+1F496
+```
+
+
+### 可扩展的字形群集(Extended Grapheme Clusters)
+每一个 Swift 的`Character`类型代表一个可扩展的字形群。
+一个可扩展的字形群是一个或者更多可生成人类可读的字符 Unicode 标量的有序排列。
+举个例子,字母 é 可以用单一的 Unicode 标量 é (`LATIN SMALL LETTER E WITH ACUTE`, 或者`U+00E9`)来表示。然而一个标准的字母 e (`LATIN SMALL LETTER E`或者`U+0065`) 加上一个急促重音(`COMBINING ACTUE ACCENT`)的标量(`U+0301`),这样一对标量就表示了同样的字母 é。
+这个急促重音的标量形象的将 e 转换成了 é。
+在这两种情况中,字母 é 代表了一个单一的 Swift 的字符串,同时代表了一个可扩展的字形群。
+在第一种情况,这个字形群包含一个单一标量;而在第二种情况,它是包含两个标量的字形群:
+
+```
+let eAcute: Character = "\u{E9}" // é
+let combinedEAcute: Character = "\u{65}\u{301}" // e 后面加上 ́
+// eAcute 是 é, combinedEAcute 是 é
+```
+
+可扩展的字符群集是一个灵活的方法,用许多复杂的脚本字符表示单一字符。
+例如,来自朝鲜语字母表的韩语音节能表示为组合或分解的有序排列。
+在 Swift 都会表示为同一个单一的字符:
+
+
+```
+let precomposed: Character = "\u{D55C}" // 한
+let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
+// precomposed 是 한, decomposed 是 한
+```
+
+可拓展的字符群集可以使包围记号(例如`COMBINING ENCLOSING CIRCLE`或者`U+20DD`)的标量包围其他 Unicode 标量,作为一个单一的字符:
+
+```
+let enclosedEAcute: Character = "\u{E9}\u{20DD}"
+// enclosedEAcute 是 é⃝
+```
+
+局部的指示符号的 Unicode 标量可以组合成一个单一的字符,例如 `REGIONAL INDICATOR SYMBOL LETTER U`(`U+1F1FA`)和`REGIONAL INDICATOR SYMBOL LETTER S`(`U+1F1F8`):
+
+
+```
+let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
+// regionalIndicatorForUS 是 🇺🇸
+```
+
+
+## 计算字符数量 (Counting Characters)
+
+调用字符串的`count`属性,就可以获取一个字符串的字符数量:
+
+
+```
+let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
+print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
+// 打印输出:"unusualMenagerie has 40 characters"
+```
+
+注意在 Swift 中,使用可拓展的字符群集作为字符来连接或改变字符串时,并不一定会更改字符串的字符数量。
+例如,如果你用四个字符的单词 cafe 初始化一个新的字符串,然后添加一个 `COMBINING ACTUE ACCENT`(`U+0301`)作为字符串的结尾。最终这个字符串的字符数量仍然是4,因为第四个字符是 é ,而不是 e :
+
+```
+var word = "cafe"
+print("the number of characters in \(word) is \(word.characters.count)")
+// 打印输出 "the number of characters in cafe is 4"
+word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301
+print("the number of characters in \(word) is \(word.characters.count)")
+// 打印输出 "the number of characters in café is 4"
+```
+
+> 注意:
+> 可扩展的字符群集可以组成一个或者多个 Unicode 标量。这意味着不同的字符以及相同字符的不同表示方式可能需要不同数量的内存空间来存储。所以 Swift 中的字符在一个字符串中并不一定占用相同的内存空间数量。因此在没有获取字符串的可扩展的字符群的范围时候,就不能计算出字符串的字符数量。如果您正在处理一个长字符串,需要注意`characters`属性必须遍历全部的 Unicode 标量,来确定字符串的字符数量。
+> 另外需要注意的是通过`characters`返回的字符数量并不总是与包含相同字符的`NSString`的`length`属性相同。`NSString`的`length`属性是利用 UTF-16 表示的十六位代码单元数字,而不是 Unicode 可扩展的字符群集。
+
+
+
+## 访问和修改字符串 (Accessing and Modifying a String)
+你可以通字符串的属性和方法来访问和读取一个它,当然也可以用下标语法完成。
+
+
+### 字符串索引 (String Indices)
+每一个字符串都有一个关联的索引(*index*)类型,`String.index`,它对应着字符串中的每一个字符的位置。
+前面提到,不同的字符可能会占用不同的内存空间数量,所以要知道字符的确定位置,就必须从字符串开头遍历每一个 Unicode 标量到字符串结尾。因此,Swift 的字符串不能用整数(integer)做索引。
+使用`startIndex`属性可以获取字符串的第一个字符。使用`endIndex`属性可以获取最后一个字符的末尾位置。如果字符串是空值,`startIndex`和`endIndex`是相等的。
+通过调用`String.Index`的`predecessor()`方法,可以立即得到前面一个索引,调用`successor()`方法可以立即得到后面一个索引。任何一个字符串的索引都可以通过锁链作用的这些方法来获取另一个索引,也可以调用`advance(start:n:)`函数来获取。但如果尝试获取出界的字符串索引,就会抛出一个运行时错误。
+你可以使用下标语法来访问字符在字符串的确切索引。尝试获取出界的字符串索引,仍然抛出一个运行时错误。
+
+```
+let greeting = "Guten Tag"
+greeting[greeting.startIndex]
+// G
+greeting[greeting.endIndex.predecessor()]
+// g
+greeting[greeting.startIndex.successor()]
+// u
+let index = advance(greeting.startIndex, 7)
+greeting[index]
+// a
+greeting[greeting.endIndex] // 错误
+greeting.endIndex.successor() // 错误
+```
+
+使用`characters`属性的`indices`会创建一个包含全部索引的范围(`Range`),用来在一个字符串中访问分立的字符。
+
+```
+for index in greeting.characters.indices {
+ print("\(greeting[index]) ", appendNewline: false)
+}
+// 打印输出 "G u t e n T a g !"
+```
+
+
+### 插入和删除 (Inserting and Removing)
+调用`insert(_:atIndex:)`方法可以在一个字符串的指定索引插入一个字符。
+
+```
+var welcome = "hello"
+welcome.insert("!", atIndex: welcome.endIndex)
+// welcome now 现在等于 "hello!"
+```
+
+调用`splice(_:atIndex:)`方法可以在一个字符串的指定索引插入一个字符串。
+
+```
+welcome.splice(" there".characters, atIndex: welcome.endIndex.predecessor())
+// welcome 现在等于 "hello there!"
+```
+
+调用`removeAtIndex(_:)`方法可以在一个字符串的指定索引删除一个字符。
+
+```
+welcome.removeAtIndex(welcome.endIndex.predecessor())
+// welcome 现在等于 "hello there"
+// 翻译的人解释:最后还有一个换行符,所以这里删除的是 !
+```
+
+调用`removeRange(_:)`方法可以在一个字符串的指定索引删除一个子字符串。
+
+```
+let range = advance(welcome.endIndex, -6)..
+## 比较字符串 (Comparing Strings)
+
+Swift 提供了三种方式来比较文本值:字符串字符相等、前缀相等和后缀相等。
+
+
+### 字符串/字符相等 (String and Character Equality)
+字符串/字符可以用等于操作符(`==`)和不等于操作符(`!=`),详细描述在 [Comparison Operators](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID70):
+
+```
+let quotation = "We're a lot alike, you and I."
+let sameQuotation = "We're a lot alike, you and I."
+if quotation == sameQuotation {
+ print("These two strings are considered equal")
+}
+// 打印输出 "These two strings are considered equal"
+```
+
+如果两个字符串(或者两个字符)的可扩展的字形群集是标准相等的,那就认为它们是相等的。在这个情况下,即使可扩展的字形群集是有不同的 Unicode 标量构成的,只要它们有同样的语言意义和外观,就认为它们标准相等。
+例如,`LATIN SMALL LETTER E WITH ACUTE`(`U+00E9`)就是标准相等于`LATIN SMALL LETTER E`(`U+0065`)后面加上`COMBINING ACUTE ACCENT`(`U+0301`)。这两个字符群集都有效的表示字符 é ,所以它们被认为是标准相等的:
+
+```
+// "Voulez-vous un café?" 使用 LATIN SMALL LETTER E WITH ACUTE
+let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"
+// "Voulez-vous un café?" 使用 LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
+let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"
+if eAcuteQuestion == combinedEAcuteQuestion {
+ print("These two strings are considered equal")
+}
+// 打印输出 "These two strings are considered equal"
+```
+
+相反,英语中的`LATIN CAPITAL LETTER A`(`U+0401`,或者`A`)不等于俄语中的`CYRILLIC CAPITAL LETTER A`(`U+0410`,或者`A`)。两个字符看着是一样的,但却有不同的语言意义:
+
+```
+let latinCapitalLetterA: Character = "\u{41}"
+let cyrillicCapitalLetterA: Character = "\u{0410}"
+if latinCapitalLetterA != cyrillicCapitalLetterA {
+ print("These two characters are not equivalent")
+}
+// 打印 "These two characters are not equivalent"
+```
+
+> 注意:
+> 在 Swift 中,字符串和字符并不区分区域。
+
+
+
+### 前缀/后缀相等 (Prefix and Suffix Equality)
+
+通过调用字符串的`hasPrefix(_:)`/`hasSuffix(_:)`方法来检查字符串是否拥有特定前缀/后缀,两个方法均需要以字符串作为参数传入并传出`Boolean`值。
+下面的例子以一个字符串数组表示莎士比亚话剧《罗密欧与朱丽叶》中前两场的场景位置:
+
+```
+let romeoAndJuliet = [
+ "Act 1 Scene 1: Verona, A public place",
+ "Act 1 Scene 2: Capulet's mansion",
+ "Act 1 Scene 3: A room in Capulet's mansion",
+ "Act 1 Scene 4: A street outside Capulet's mansion",
+ "Act 1 Scene 5: The Great Hall in Capulet's mansion",
+ "Act 2 Scene 1: Outside Capulet's mansion",
+ "Act 2 Scene 2: Capulet's orchard",
+ "Act 2 Scene 3: Outside Friar Lawrence's cell",
+ "Act 2 Scene 4: A street in Verona",
+ "Act 2 Scene 5: Capulet's mansion",
+ "Act 2 Scene 6: Friar Lawrence's cell"
+]
+```
+
+您可以调用`hasPrefix(_:)`方法来计算话剧中第一幕的场景数:
+
+```
+var act1SceneCount = 0
+for scene in romeoAndJuliet {
+ if scene.hasPrefix("Act 1 ") {
+ ++act1SceneCount
+ }
+}
+print("There are \(act1SceneCount) scenes in Act 1")
+// 打印输出 "There are 5 scenes in Act 1"
+```
+
+相似地,您可以用`hasSuffix(_:)`方法来计算发生在不同地方的场景数:
+
+```
+var mansionCount = 0
+var cellCount = 0
+for scene in romeoAndJuliet {
+ if scene.hasSuffix("Capulet's mansion") {
+ ++mansionCount
+ } else if scene.hasSuffix("Friar Lawrence's cell") {
+ ++cellCount
+ }
+}
+print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
+// 打印输出 "6 mansion scenes; 2 cell scenes"
+```
+
+> 注意:
+> `hasPrefix(_:)`和`hasSuffix(_:)`方法都是在每个字符串中一个一个字符的比较其可扩展的字符群集是否标准相等,详细描述在[字符串/字符相等](#string_and_character_equality)。
+
-### 字符串的 Unicode 表示(Unicode Representations of Strings)
+## 字符串的 Unicode 表示形式(Unicode Representations of Strings)
+当一个 Unicode 字符串被写进文本文件或者其他储存时,字符串中的 Unicode 标量会用 Unicode 定义的几种编码格式编码。每一个字符串中的小块编码都被称为代码单元。这些包括 UTF-8 编码格式(编码字符串为8位的代码单元), UTF-16 编码格式(编码字符串位16位的代码单元),以及 UTF-32 编码格式(编码字符串32位的代码单元)。
-Swift 提供了几种不同的方式来访问字符串的 Unicode 表示。
-
-您可以利用`for-in`来对字符串进行遍历,从而以 Unicode 字符的方式访问每一个字符值。
+Swift 提供了几种不同的方式来访问字符串的 Unicode 表示形式。
+您可以利用`for-in`来对字符串进行遍历,从而以 Unicode 可扩展的字符群集的方式访问每一个字符值。
该过程在 [使用字符](#working_with_characters) 中进行了描述。
另外,能够以其他三种 Unicode 兼容的方式访问字符串的值:
* UTF-8 代码单元集合 (利用字符串的`utf8`属性进行访问)
* UTF-16 代码单元集合 (利用字符串的`utf16`属性进行访问)
-* 21位的 Unicode 标量值集合 (利用字符串的`unicodeScalars`属性进行访问)
+* 21位的 Unicode 标量值集合,也就是字符串的 UTF-32 编码格式 (利用字符串的`unicodeScalars`属性进行访问)
-下面由`D``o``g``!`和`🐶`(`DOG FACE`,Unicode 标量为`U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示:
+下面由`D``o``g``‼`(`DOUBLE EXCLAMATION MARK`, Unicode 标量 `U+203C`)和`🐶`(`DOG FACE`,Unicode 标量为`U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示:
-```swift
-let dogString = "Dog!🐶"
-```
+```
+let dogString = "Dog‼🐶"
+```
-
-### UTF-8
+
+### UTF-8 表示
您可以通过遍历字符串的`utf8`属性来访问它的`UTF-8`表示。
-其为`UTF8View`类型的属性,`UTF8View`是无符号8位 (`UInt8`) 值的集合,每一个`UInt8`值都是一个字符的 UTF-8 表示:
+其为`String.UTF8View`类型的属性,`UTF8View`是无符号8位 (`UInt8`) 值的集合,每一个`UInt8`值都是一个字符的 UTF-8 表示:
+
+
+
+
+
+ | Character |
+ D U+0044 |
+ o U+006F |
+ g U+0067 |
+ ‼ U+1F436 |
+ 🐶 U+1F436 |
+
+
+ UTF-8 Code Unit |
+ 68 |
+ 111 |
+ 103 |
+ 226 |
+ 128 |
+ 188 |
+ 240 |
+ 159 |
+ 144 |
+ 182 |
+
+
+ | Position |
+ 0 |
+ 1 |
+ 2 |
+ 3 |
+ 4 |
+ 5 |
+ 6 |
+ 7 |
+ 8 |
+ 9 |
+
+
+
+
-```swift
-for codeUnit in dogString.utf8 {
- print("\(codeUnit) ")
-}
-print("\n")
-// 68 111 103 33 240 159 144 182
+```
+for codeUnit in dogString.utf8 {
+ print("\(codeUnit) ", appendNewline: false)
+}
+print("")
+// 68 111 103 226 128 188 240 159 144 182
```
-上面的例子中,前四个10进制代码单元值 (68, 111, 103, 33) 代表了字符`D` `o` `g`和`!`,它们的 UTF-8 表示与 ASCII 表示相同。
-后四个代码单元值 (240, 159, 144, 182) 是`DOG FACE`的4字节 UTF-8 表示。
+上面的例子中,前三个10进制代码单元值 (68, 111, 103) 代表了字符`D`、`o`和 `g`,它们的 UTF-8 表示与 ASCII 表示相同。
+接下来的三个10进制代码单元值 (226, 128, 188) 是`DOUBLE EXCLAMATION MARK`的3字节 UTF-8 表示。
+最后的四个代码单元值 (240, 159, 144, 182) 是`DOG FACE`的4字节 UTF-8 表示。
-
-### UTF-16
+
+
+### UTF-16 表示
您可以通过遍历字符串的`utf16`属性来访问它的`UTF-16`表示。
-其为`UTF16View`类型的属性,`UTF16View`是无符号16位 (`UInt16`) 值的集合,每一个`UInt16`都是一个字符的 UTF-16 表示:
+其为`String.UTF16View`类型的属性,`UTF16View`是无符号16位 (`UInt16`) 值的集合,每一个`UInt16`都是一个字符的 UTF-16 表示:
+
+
+
+
+ | Character |
+ D U+0044 |
+ o U+006F |
+ g U+0067 |
+ ‼ U+1F436 |
+ 🐶 U+1F436 |
+
+
+ UTF-16 Code Unit |
+ 68 |
+ 111 |
+ 103 |
+ 8252 |
+ 55357 |
+ 56374 |
+
+
+ | Position |
+ 0 |
+ 1 |
+ 2 |
+ 3 |
+ 4 |
+ 5 |
+
+
+
+
-```swift
-for codeUnit in dogString.utf16 {
- print("\(codeUnit) ")
-}
-print("\n")
-// 68 111 103 33 55357 56374
+
+```
+for codeUnit in dogString.utf16 {
+ print("\(codeUnit) ", appendNewline: false)
+}
+print("")
+// 68 111 103 8252 55357 56374
```
-同样,前四个代码单元值 (68, 111, 103, 33) 代表了字符`D` `o` `g`和`!`,它们的 UTF-16 代码单元和 UTF-8 完全相同。
-
-第五和第六个代码单元值 (55357 和 56374) 是`DOG FACE`字符的UTF-16 表示。
+同样,前三个代码单元值 (68, 111, 103) 代表了字符`D`、`o`和`g`,它们的 UTF-16 代码单元和 UTF-8 完全相同(因为这些 Unicode 标量表示 ASCII 字符)。
+第四个代码单元值 (8252) 是一个等于十六进制203C的的十进制值。这个代表了`DOUBLE EXCLAMATION MARK`字符的 Unicode 标量值`U+203C`。这个字符在 UTF-16 中可以用一个代码单元表示。
+第五和第六个代码单元值 (55357 和 56374) 是`DOG FACE`字符的UTF-16 表示。
第一个值为`U+D83D`(十进制值为 55357),第二个值为`U+DC36`(十进制值为 56374)。
-
-### Unicode 标量 (Unicode Scalars)
+
+### Unicode 标量表示 (Unicode Scalars Representation)
您可以通过遍历字符串的`unicodeScalars`属性来访问它的 Unicode 标量表示。
其为`UnicodeScalarView`类型的属性, `UnicodeScalarView`是`UnicodeScalar`的集合。
`UnicodeScalar`是21位的 Unicode 代码点。
-每一个`UnicodeScalar`拥有一个值属性,可以返回对应的21位数值,用`UInt32`来表示。
+每一个`UnicodeScalar`拥有一个值属性,可以返回对应的21位数值,用`UInt32`来表示:
+
+
+
+
+
+ | Character |
+ D U+0044 |
+ o U+006F |
+ g U+0067 |
+ ‼ U+1F436 |
+ 🐶 U+1F436 |
+
+
+ UTF-16 Code Unit |
+ 68 |
+ 111 |
+ 103 |
+ 8252 |
+ 128054 |
+
+
+ | Position |
+ 0 |
+ 1 |
+ 2 |
+ 3 |
+ 4 |
+
+
+
+
-```swift
-for scalar in dogString.unicodeScalars {
- print("\(scalar.value) ")
-}
-print("\n")
-// 68 111 103 33 128054
+
+```
+for scalar in dogString.unicodeScalars {
+ print("\(scalar.value) ", appendNewline: false)
+}
+print("")
+// 68 111 103 8252 128054
```
-同样,前四个代码单元值 (68, 111, 103, 33) 代表了字符`D` `o` `g`和`!`。
-第五位数值,128054,是一个十六进制1F436的十进制表示。
-其等同于`DOG FACE`的Unicode 标量 U+1F436。
+前三个代码单元值 (68, 111, 103) 仍然代表字符`D`、`o`和`g`。
+第四个代码单元值 (8252) 仍然是一个等于十六进制203C的的十进制值。这个代表了`DOUBLE EXCLAMATION MARK`字符的 Unicode 标量`U+203C`。
+第五位数值,128054,是一个十六进制1F436的十进制表示。其等同于`DOG FACE`的Unicode 标量`U+1F436`。
作为查询字符值属性的一种替代方法,每个`UnicodeScalar`值也可以用来构建一个新的字符串值,比如在字符串插值中使用:
-```swift
-for scalar in dogString.unicodeScalars {
- println("\(scalar) ")
-}
-// D
-// o
-// g
-// !
+```
+for scalar in dogString.unicodeScalars {
+ print("\(scalar) ")
+}
+// D
+// o
+// g
+// ‼
// 🐶
-```
+```
From 727346de2e5c99201b63fd6081c453d130d47855 Mon Sep 17 00:00:00 2001
From: DianQK
Date: Sun, 5 Jul 2015 20:13:32 +0800
Subject: [PATCH 081/228] update Methods
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
add mark “swift” at String and Characters
update Methods
---
source/chapter2/03_Strings_and_Characters.md | 68 ++++++------
source/chapter2/11_Methods.md | 109 +++++++++----------
2 files changed, 85 insertions(+), 92 deletions(-)
diff --git a/source/chapter2/03_Strings_and_Characters.md b/source/chapter2/03_Strings_and_Characters.md
index 13d5dd3d..1ad844a4 100755
--- a/source/chapter2/03_Strings_and_Characters.md
+++ b/source/chapter2/03_Strings_and_Characters.md
@@ -51,14 +51,14 @@ Swift 的`String`和`Character`类型提供了一个快速的,兼容 Unicode
要创建一个空字符串作为初始值,可以将空的字符串字面量赋值给变量,也可以初始化一个新的`String`实例:
-```
+```swift
var emptyString = "" // 空字符串字面量
var anotherEmptyString = String() // 初始化方法
// 两个字符串均为空并等价。
```
您可以通过检查其`Boolean`类型的`isEmpty`属性来判断该字符串是否为空:
-```
+```swift
if emptyString.isEmpty {
print("Nothing to see here")
}
@@ -70,7 +70,7 @@ if emptyString.isEmpty {
您可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改:
-```
+```swift
var variableString = "Horse"
variableString += " and carriage"
// variableString 现在为 "Horse and carriage"
@@ -104,7 +104,7 @@ Swift 默认字符串拷贝的方式保证了在函数/方法中传递的是字
您可通过`for-in`循环来遍历字符串中的`characters`属性来获取每一个字符的值:
-```
+```swift
for character in "Dog!🐶".characters {
print(character)
}
@@ -119,12 +119,12 @@ for-in 循环在 [For Loops](05_Control_Flow.html#for_loops) 中进行了详细
另外,通过标明一个`Character`类型并用字符字面量进行赋值,可以建立一个独立的字符常量或变量:
-```
+```swift
let exclamationMark: Charater = "!"
```
字符串可以通过传递一个值类型为`Charater`的数组作为自变量来初始化:
-```
+```swift
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
@@ -136,7 +136,7 @@ print(catString)
字符串可以通过加法运算符(`+`)相加在一起(或称“连接”)创建一个新的字符串:
-```
+```swift
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
@@ -145,7 +145,7 @@ var welcome = string1 + string2
您也可以通过加法赋值运算符 (`+=`) 将一个字符串添加到一个已经存在字符串变量上:
-```
+```swift
var instruction = "look over"
instruction += string2
// instruction 现在等于 "look over there"
@@ -153,7 +153,7 @@ instruction += string2
您可以用`append`方法将一个字符附加到一个字符串变量的尾部:
-```
+```swift
let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome 现在等于 "hello there!"
@@ -169,7 +169,7 @@ welcome.append(exclamationMark)
字符串插值是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式。
您插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中:
-```
+```swift
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message 是 "3 times 2.5 is 7.5"
@@ -215,7 +215,7 @@ Unicode 标量是对应字符的唯一21位数字或者修饰符,例如`U+0061
`wiseWords`常量包含了两个双引号;
`dollarSign`、`blackHeart`和`sparklingHeart`常量演示了三种不同格式的 Unicode 标量:
-```
+```swift
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
// "Imageination is more important than knowledge" - Enistein
let dollarSign = "\u{24}" // $, Unicode 标量 U+0024
@@ -232,7 +232,7 @@ let sparklingHeart = "\u{1F496}" // 💖, Unicode 标量 U+1F496
在这两种情况中,字母 é 代表了一个单一的 Swift 的字符串,同时代表了一个可扩展的字形群。
在第一种情况,这个字形群包含一个单一标量;而在第二种情况,它是包含两个标量的字形群:
-```
+```swift
let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}" // e 后面加上 ́
// eAcute 是 é, combinedEAcute 是 é
@@ -243,7 +243,7 @@ let combinedEAcute: Character = "\u{65}\u{301}" // e 后面加上 ́
在 Swift 都会表示为同一个单一的字符:
-```
+```swift
let precomposed: Character = "\u{D55C}" // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
// precomposed 是 한, decomposed 是 한
@@ -251,7 +251,7 @@ let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
可拓展的字符群集可以使包围记号(例如`COMBINING ENCLOSING CIRCLE`或者`U+20DD`)的标量包围其他 Unicode 标量,作为一个单一的字符:
-```
+```swift
let enclosedEAcute: Character = "\u{E9}\u{20DD}"
// enclosedEAcute 是 é⃝
```
@@ -259,7 +259,7 @@ let enclosedEAcute: Character = "\u{E9}\u{20DD}"
局部的指示符号的 Unicode 标量可以组合成一个单一的字符,例如 `REGIONAL INDICATOR SYMBOL LETTER U`(`U+1F1FA`)和`REGIONAL INDICATOR SYMBOL LETTER S`(`U+1F1F8`):
-```
+```swift
let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
// regionalIndicatorForUS 是 🇺🇸
```
@@ -270,7 +270,7 @@ let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
调用字符串的`count`属性,就可以获取一个字符串的字符数量:
-```
+```swift
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
// 打印输出:"unusualMenagerie has 40 characters"
@@ -279,7 +279,7 @@ print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
注意在 Swift 中,使用可拓展的字符群集作为字符来连接或改变字符串时,并不一定会更改字符串的字符数量。
例如,如果你用四个字符的单词 cafe 初始化一个新的字符串,然后添加一个 `COMBINING ACTUE ACCENT`(`U+0301`)作为字符串的结尾。最终这个字符串的字符数量仍然是4,因为第四个字符是 é ,而不是 e :
-```
+```swift
var word = "cafe"
print("the number of characters in \(word) is \(word.characters.count)")
// 打印输出 "the number of characters in cafe is 4"
@@ -305,7 +305,7 @@ print("the number of characters in \(word) is \(word.characters.count)")
通过调用`String.Index`的`predecessor()`方法,可以立即得到前面一个索引,调用`successor()`方法可以立即得到后面一个索引。任何一个字符串的索引都可以通过锁链作用的这些方法来获取另一个索引,也可以调用`advance(start:n:)`函数来获取。但如果尝试获取出界的字符串索引,就会抛出一个运行时错误。
你可以使用下标语法来访问字符在字符串的确切索引。尝试获取出界的字符串索引,仍然抛出一个运行时错误。
-```
+```swift
let greeting = "Guten Tag"
greeting[greeting.startIndex]
// G
@@ -322,7 +322,7 @@ greeting.endIndex.successor() // 错误
使用`characters`属性的`indices`会创建一个包含全部索引的范围(`Range`),用来在一个字符串中访问分立的字符。
-```
+```swift
for index in greeting.characters.indices {
print("\(greeting[index]) ", appendNewline: false)
}
@@ -333,7 +333,7 @@ for index in greeting.characters.indices {
### 插入和删除 (Inserting and Removing)
调用`insert(_:atIndex:)`方法可以在一个字符串的指定索引插入一个字符。
-```
+```swift
var welcome = "hello"
welcome.insert("!", atIndex: welcome.endIndex)
// welcome now 现在等于 "hello!"
@@ -341,14 +341,14 @@ welcome.insert("!", atIndex: welcome.endIndex)
调用`splice(_:atIndex:)`方法可以在一个字符串的指定索引插入一个字符串。
-```
+```swift
welcome.splice(" there".characters, atIndex: welcome.endIndex.predecessor())
// welcome 现在等于 "hello there!"
```
调用`removeAtIndex(_:)`方法可以在一个字符串的指定索引删除一个字符。
-```
+```swift
welcome.removeAtIndex(welcome.endIndex.predecessor())
// welcome 现在等于 "hello there"
// 翻译的人解释:最后还有一个换行符,所以这里删除的是 !
@@ -356,7 +356,7 @@ welcome.removeAtIndex(welcome.endIndex.predecessor())
调用`removeRange(_:)`方法可以在一个字符串的指定索引删除一个子字符串。
-```
+```swift
let range = advance(welcome.endIndex, -6)..