diff --git a/source/chapter2/20_Extensions.md b/source/chapter2/20_Extensions.md index 1663bc79..71e493d9 100755 --- a/source/chapter2/20_Extensions.md +++ b/source/chapter2/20_Extensions.md @@ -96,11 +96,8 @@ println("A marathon is \(aMarathon) meters long") 扩展能向类中添加新的便利构造器,但是它们不能向类中添加新的指定构造器或析构函数。指定构造器和析构函数必须总是由原始的类实现来提供。 > 注意: -如果你使用扩展向一个值类型添加一个构造器,该构造器向所有的存储属性提供默认值,而且没有定义任何定制构造器(custom initializers),那么对于来自你的扩展构造器中的值类型,你可以调用默认构造器(default initializers)和逐一成员构造器(memberwise initializers)。 -正如在值类型的构造器授权中描述的,如果你已经把构造器写成值类型原始实现的一部分,上述规则不再适用。 +如果你使用扩展向一个值类型添加一个构造器,在该值类型已经向所有的存储属性提供默认值,而且没有定义任何定制构造器(custom initializers)时,你可以在值类型的扩展构造器中调用默认构造器(default initializers)和逐一成员构造器(memberwise initializers)。 - -如果你使用扩展向一个值类型添加一个构造器,如果该值类型已经向所有的存储属性提供默认值,而且没有定义任何定制构造器(custom initializers),那么你可以在值类型的扩展构造器中调用默认构造器(default initializers)和逐一成员构造器(memberwise initializers)。 正如在值类型的构造器委托中描述的,如果你已经把构造器写成值类型原始实现的一部分,上述规则不再适用。 diff --git a/source/chapter2/22_Generics.md b/source/chapter2/22_Generics.md index 35b48c32..623667c9 100755 --- a/source/chapter2/22_Generics.md +++ b/source/chapter2/22_Generics.md @@ -1,4 +1,4 @@ - + > 翻译:[takalard](https://github.com/takalard) > 校对:[lifedim](https://github.com/lifedim) @@ -320,9 +320,9 @@ let stringIndex = findIndex(["Mike", "Malcolm", "Andrea"], "Andrea") ``` -##关联类型 +##关联类型(Associated Types) -当定义一个协议时,有的时候声明一个或多个关联类型作为协议定义的一部分是非常有用的。一个关联类型给定作用于协议部分的类型一个节点名(或*别名*)。作用于关联类型上实际类型是不需要指定的,直到该协议接受。关联类型被指定为`typealias`关键字。 +当定义一个协议时,有的时候声明一个或多个关联类型作为协议定义的一部分是非常有用的。一个关联类型作为协议的一部分,给定了类型的一个占位名(或别名)。作用于关联类型上实际类型在协议被实现前是不需要指定的。关联类型被指定为`typealias`关键字。 ### 关联类型行为 @@ -343,19 +343,19 @@ protocol Container { - 必须可能通过使用`count`属性获取容器里items的数量,并返回一个`Int`值; - 必须可能通过容器的`Int`索引值下标可以检索到每一个item。 -这个协议没有指定容器里item是如何存储的或何种类型是允许的。这个协议只指定三个任何遵循`Container`类型所必须支持的功能点。一个遵循的类型也可以提供其他额外的功能,只要满足这三个条件。 +这个协议没有指定容器里item是如何存储的或何种类型是允许的。这个协议只指定三个任何遵循`Container`类型所必须支持的功能点。一个遵循的类型在满足这三个条件的情况下也可以提供其他额外的功能。 任何遵循`Container`协议的类型必须指定存储在其里面的值类型,必须保证只有正确类型的items可以加进容器里,必须明确可以通过其下标返回item类型。 为了定义这三个条件,`Container`协议需要一个方法指定容器里的元素将会保留,而不需要知道特定容器的类型。`Container`协议需要指定任何通过`append`方法添加到容器里的值和容器里元素是相同类型,并且通过容器下标返回的容器元素类型的值的类型是相同类型。 -为了达到此目的,`Container`协议声明了一个ItemType的关联类型,写作`typealias ItemType`。这个协议不会定义`ItemType`是什么的别名,这个信息留给了任何遵循协议的类型来提供。尽管如此,`ItemType`别名支持一种方法识别在一个容器里的items类型,以及定义一种使用在`append`方法和下标中的类型,以便保证任何期望的`Container`的行为是强制性的。 +为了达到此目的,`Container`协议声明了一个ItemType的关联类型,写作`typealias ItemType`。这个协议不会定义`ItemType`是什么的别名,这个信息将由任何遵循协议的类型来提供。尽管如此,`ItemType`别名提供了一种识别Container中Items类型的方法,并且用于`append`方法和`subscript`方法的类型定义,以便保证任何`Container`期望的行为能够被执行。 -这里是一个早前IntStack类型的非泛型版本,适用于遵循Container协议: +这里是一个早前IntStack类型的非泛型版本,遵循Container协议: ```swift struct IntStack: Container { - // original IntStack implementation + // IntStack的原始实现 var items = Int[]() mutating func push(item: Int) { items.append(item) @@ -363,7 +363,7 @@ struct IntStack: Container { mutating func pop() -> Int { return items.removeLast() } - // conformance to the Container protocol + // 遵循Container协议的实现 typealias ItemType = Int mutating func append(item: Int) { self.push(item) @@ -427,13 +427,13 @@ extension Array: Container {} ## Where 语句 -[类型约束](#type_constraints)中描述的类型约束确保你定义关于类型参数的需求和一泛型函数或类型有关联。 +[类型约束](#type_constraints)能够确保类型符合泛型函数或类的定义约束。 -对于关联类型的定义需求也是非常有用的。你可以通过这样去定义*where语句*作为一个类型参数队列的一部分。一个`where`语句使你能够要求一个关联类型遵循一个特定的协议,以及(或)那个特定的类型参数和关联类型可以是相同的。你可写一个`where`语句,通过紧随放置`where`关键字在类型参数队列后面,其后跟着一个或者多个针对关联类型的约束,以及(或)一个或多个类型和关联类型的等于关系。 +对关联类型定义约束是非常有用的。你可以在参数列表中通过*where*语句定义参数的约束。一个`where`语句能够使一个关联类型遵循一个特定的协议,以及(或)那个特定的类型参数和关联类型可以是相同的。你可以写一个`where`语句,紧跟在在类型参数列表后面,where语句后跟一个或者多个针对关联类型的约束,以及(或)一个或多个类型和关联类型间的等价(equality)关系。 -下面的列子定义了一个名为`allItemsMatch`的泛型函数,用来检查是否两个`Container`单例包含具有相同顺序的相同元素。如果匹配到所有的元素,那么返回一个为`true`的`Boolean`值,反之,则相反。 +下面的例子定义了一个名为`allItemsMatch`的泛型函数,用来检查两个`Container`实例是否包含相同顺序的相同元素。如果所有的元素能够匹配,那么返回一个为`true`的`Boolean`值,反之则为`false`。 -这两个容器可以被检查出是否是相同类型的容器(虽然它们可以是),但它们确实拥有相同类型的元素。这个需求通过一个类型约束和`where`语句结合来表示: +被检查的两个`Container`可以不是相同类型的容器(虽然它们可以是),但它们确实拥有相同类型的元素。这个需求通过一个类型约束和`where`语句结合来表示: ```swift func allItemsMatch< @@ -441,19 +441,19 @@ func allItemsMatch< where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> (someContainer: C1, anotherContainer: C2) -> Bool { - // check that both containers contain the same number of items + // 检查两个Container的元素个数是否相同 if someContainer.count != anotherContainer.count { return false } - // check each pair of items to see if they are equivalent + // 检查两个Container相应位置的元素彼此是否相等 for i in 0..someContainer.count { if someContainer[i] != anotherContainer[i] { return false } } - // all items match, so return true + // 如果所有元素检查都相同则返回true return true } @@ -506,7 +506,7 @@ if allItemsMatch(stackOfStrings, arrayOfStrings) { // 输出 "All items match." ``` - 上面的例子创建一个`Stack`单例来存储`String`,然后压了三个字符串进栈。这个例子也创建了一个`Array`单例,并初始化包含三个同栈里一样的原始字符串。即便栈和数组否是不同的类型,但它们都遵循`Container`协议,而且它们都包含同样的类型值。你因此可以调用`allItemsMatch`函数,用这两个容器作为它的参数。在上面的例子中,`allItemsMatch`函数正确的显示了所有的这两个容器的`items`匹配。 + 上面的例子创建一个`Stack`单例来存储`String`,然后压了三个字符串进栈。这个例子也创建了一个`Array`单例,并初始化包含三个同栈里一样的原始字符串。即便栈和数组是不同的类型,但它们都遵循`Container`协议,而且它们都包含同样的类型值。因此你可以调用`allItemsMatch`函数,用这两个容器作为它的参数。在上面的例子中,`allItemsMatch`函数正确的显示了所有的这两个容器的`items`匹配。 [1]: ../chapter2/06_Functions.html [2]: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/stackPushPop_2x.png @@ -515,4 +515,4 @@ if allItemsMatch(stackOfStrings, arrayOfStrings) { [5]: ../chapter2/04_Collection_Types.html [6]: ../chapter2/21_Protocols.html [7]: ../chapter2/21_Protocols.html - [8]: #type_constraints + [8]: #type_constraints diff --git a/source/chapter2/23_Advanced_Operators.md b/source/chapter2/23_Advanced_Operators.md index 42ca8164..6f15ccdf 100755 --- a/source/chapter2/23_Advanced_Operators.md +++ b/source/chapter2/23_Advanced_Operators.md @@ -12,18 +12,18 @@ - [运算符函数(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支持如下所有C语言的位运算符: @@ -33,7 +33,7 @@ Swift支持如下所有C语言的位运算符: ![Art/bitwiseNOT_2x.png](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitwiseNOT_2x.png "Art/bitwiseNOT_2x.png") -这个运算符是前置的,所以请不加任何空格地写着操作数之前。 +这个运算符是前置的,所以请不加任何空格地写在操作数之前。 ```swift let initialBits: UInt8 = 0b00001111 @@ -124,9 +124,9 @@ let blueComponent = pink & 0x0000FF // blueComponent 是 0x99, 即 153 对`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`。 @@ -160,7 +160,7 @@ let blueComponent = pink & 0x0000FF // blueComponent 是 0x99, 即 153 第二,由于使用二进制补码表示,我们可以和正数一样对负数进行按位左移右移的,同样也是左移1位时乘于`2`,右移1位时除于`2`。要达到此目的,对有符整型的右移有一个特别的要求: -对有符整型按位右移时,使用符号位(正数为`0`,负数为`1`)填充空白位。 +对有符整型按位右移时,不使用0填充空白位,而是根据符号位(正数为`0`,负数为`1`)填充空白位。 ![Art/bitshiftSigned_2x.png](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/bitshiftSigned_2x.png "Art/bitshiftSigned_2x.png") @@ -200,7 +200,7 @@ potentialOverflow += 1 var willOverflow = UInt8.max // willOverflow 等于UInt8的最大整数 255 willOverflow = willOverflow &+ 1 -// 这时候 willOverflow 等于 0 +// 此时 willOverflow 等于 0 ``` `willOverflow`用`Int8`所能承载的最大值`255`(二进制`11111111`),然后用`&+`加1。然后`UInt8`就无法表达这个新值的二进制了,也就导致了这个新值上溢出了,大家可以看下图。溢出后,新值在`UInt8`的承载范围内的那部分是`00000000`,也就是`0`。 @@ -234,7 +234,7 @@ willUnderflow = willUnderflow &- 1 var signedUnderflow = Int8.min // signedUnderflow 等于最小的有符整数 -128 signedUnderflow = signedUnderflow &- 1 -// 如今 signedUnderflow 等于 127 +// 此时 signedUnderflow 等于 127 ``` ### 除零溢出 @@ -400,7 +400,7 @@ let afterIncrement = ++toIncrement ``` >注意: -默认的赋值符是不可重载的。只有组合赋值符可以重载。三目条件运算符 `a?b:c` 也是不可重载。 +默认的赋值符(=)是不可重载的。只有组合赋值符可以重载。三目条件运算符 `a?b:c` 也是不可重载。 ### 比较运算符 @@ -451,7 +451,7 @@ operator prefix +++ {} } ``` -`Vector2D` 的 `+++` 的实现和 `++` 的实现很接近, 唯一不同的前者是加自己, 后者是加值为 `(1.0, 1.0)` 的向量. +`Vector2D` 的 `+++` 的实现和 `++` 的实现很接近, 唯一不同的是前者是加自己, 后者是加值为 `(1.0, 1.0)` 的向量. ```swift var toBeDoubled = Vector2D(x: 1.0, y: 4.0) diff --git a/source/chapter3/04_Expressions.md b/source/chapter3/04_Expressions.md index 285dc7f0..b68d5c80 100755 --- a/source/chapter3/04_Expressions.md +++ b/source/chapter3/04_Expressions.md @@ -127,7 +127,6 @@ Swift 标准库提供了如下的二元运算符: ## 赋值表达式(Assignment Operator) -The assigment operator sets a new value for a given expression. It has the following form: 赋值表达式会对某个给定的表达式赋值。 它有如下的形式; > `expression` = `value` @@ -193,7 +192,6 @@ let y2: SomeType = x // Type information from an annotation 'is' 运算符在“运行时(runtime)”会做检查。 成功会返回true, 否则 false -The check must not be known to be true or false at compile time. The following are invalid: 上述检查在“编译时(compile time)”不能使用。 例如下面的使用是错误的: ```swift @@ -232,7 +230,7 @@ The check must not be known to be true or false at compile time. The following a \__COLUMN__ | Int | 所在的列数 \__FUNCTION__ | String | 所在的function 的名字 -在某个函数(function)中,`__FUNCTION__` 会返回当前函数的名字。 在某个方法(method)中,它会返回当前方法的名字。 在某个property 的getter/setter中会返回这个属性的名字。 在init/subscript中 只有的特殊成员(member)中会返回这个keyword的名字,在某个文件的顶端(the top level of a file),它返回的是当前module的名字。 +在某个函数(function)中,`__FUNCTION__` 会返回当前函数的名字。 在某个方法(method)中,它会返回当前方法的名字。 在某个property 的getter/setter中会返回这个属性的名字。 在特殊的成员如init/subscript中 会返回这个关键字的名字,在某个文件的顶端(the top level of a file),它返回的是当前module的名字。 一个array literal,是一个有序的值的集合。 它的形式是: diff --git a/source/chapter3/05_Declarations.md b/source/chapter3/05_Declarations.md index 6e4e44bf..3b6a959d 100755 --- a/source/chapter3/05_Declarations.md +++ b/source/chapter3/05_Declarations.md @@ -153,9 +153,9 @@ println("The second number is \(secondNumber).") 你可以在全局,函数内,或者在类和结构体的声明(context)中使用这种形式来声明一个变量。当变量以这种形式 在全局或者一个函数内被声明时,它代表一个存储型变量。当它在类或者结构体中被声明时,它代表一个存储型变量属性。 -构造器表达式可以被 +初始化的表达式不可以在协议(protocol)的定义中出现,在其他情况下,初始化表达式是可选的(optional),如果没有初始化表达式,那么变量定义时必须显示的声明变量类型(:type) -和常量声明相比,如果变量名是一个元祖类型,元祖的每一项的名字都要和初始化表达式一致。 +对于常量的定义,如果名字是一个元祖(tuple),元祖每一项的`name`都要和初始化表达式`expression`中的相应值一致。 正如名字一样,存储型变量的值或存储型变量属性存储在内存中。 @@ -181,7 +181,7 @@ getter用来读取变量值,setter用来写入变量值。setter子句是可 但是如果你提供了一个setter语句,你也必需提供一个getter语句。 setter的名字和圆括号内的语句是可选的。如果你写了一个setter名,它就会作为setter的参数被使用。如果你不写setter名, -setter的初始名为newValue,正如在seter声明速记(shorthand setter declaration)中提到的那样。 +setter的初始名为newValue,正如在setter声明速记(shorthand setter declaration)中提到的那样。 不像存储型变量和存储型属性那样,计算型属性和计算型变量的值不存储在内存中。 @@ -211,7 +211,7 @@ setter的初始名为newValue,正如在seter声明速记(shorthand setter decl 所有包含监视器的变量声明都必须有类型注释(type annotation)。 当变量或属性的值被改变时,willset和didset监视器提供了一个监视方法(适当的回应)。 -监视器不会在变量或属性第一次初始化时不会被运行,它们只有在值被外部初始化语句改变时才会被运行。 +监视器不会在变量或属性第一次初始化时运行,它们只有在值被外部初始化语句改变时才会被运行。 willset监视器只有在变量或属性值被改变之前运行。新的值作为一个常量经过过willset监视器,因此不可以在 willset语句中改变它。didset监视器在变量或属性值被改变后立即运行。和willset监视器相反,为了以防止你仍然 @@ -259,7 +259,7 @@ class关键字用来声明类的计算型属性。static关键字用来声明类 > `typealias name` = `existing type` -当一个类型被别名被声明后,你可以在你程序的任何地方使用别名来代替已存在的类型。已存在的类型可以是已经被命名的 +当声明一个类型的别名后,你可以在你程序的任何地方使用别名来代替已存在的类型。已存在的类型可以是已经被命名的 类型或者是混合类型。类型的别名不产生新的类型,它只是简单的和已存在的类型做名称替换。 查看更多Protocol Associated Type Declaration. @@ -286,7 +286,7 @@ class关键字用来声明类的计算型属性。static关键字用来声明类 > `statements` > } -每个参数的类型都要标明,它们不能被推断出来。初始时函数的参数是常值。在这些参数前面添加var使它们成为变量, +每个参数的类型都要标明,它们不能被推断出来。初始时函数的参数是常量。在这些参数前面添加var使它们成为变量, 作用域内任何对变量的改变只在函数体内有效,或者用inout使的这些改变可以在调用域内生效。 更多关于in-out参数的讨论,参见in-out参数(in-out parameters) @@ -349,8 +349,8 @@ c.f(7, y: "hello") // x没有名称,y有名称 且必须是最后一个参数。可变参数被作为该基本类型名的数组来看待。举例来讲,可变参数int...被看做是int[]。 查看可变参数的使用例子,详见可变参数(variadic parameters)一节。 -在参数的类型后面有一个以等号(=)连接的表达式,这样的参数被看做有着给定表达式的初试值。如果参数在函数 -调用时被省略了,就会使用初始值。如果参数没有胜率,那么它在函数调用是必须有自己的名字.举例来讲, +在参数的类型后面有一个以等号(=)连接的表达式,这样的参数被看做有着给定表达式的初始值。如果参数在函数 +调用时被省略了,就会使用初始值。如果参数没有省略,那么它在函数调用是必须有自己的名字.举例来讲, f()和f(x:7)都是只有一个变量x的函数的有效调用,但是f(7)是非法的,因为它提供了一个值而不是名称。 ###特殊方法 @@ -362,7 +362,7 @@ f()和f(x:7)都是只有一个变量x的函数的有效调用,但是f(7)是非 和类型相关而不是和类型实例相关的方法必须在static声明的结构以或枚举内,亦或是以class关键字定义的类内。 -###柯里化函数和方法 +###柯里化函数和方法(Curried Functions and Methods) 柯里化函数或方法有着如下的形式: @@ -370,7 +370,7 @@ f()和f(x:7)都是只有一个变量x的函数的有效调用,但是f(7)是非 > `statements` > } -以这种形式定义的函数的返回值是另一个函数。举例来说,下面的两个声明时等价的: +以这种形式定义的函数的返回值是另一个函数。举例来说,下面的两个声明是等价的: ```swift func addTwoNumbers(a: Int)(b: Int) -> Int { @@ -546,8 +546,8 @@ ExampleEnum.D的值会自动增长为6. 一个类只能继承一个父类,超类,但是可以包含任意数量的协议。这些超类第一次在type-inheritance-clause出现,遵循任意协议。 -正如在初始化声明(Initializer Declaration)谈及的那样,类可以有指定和方便的构造器。当你声明任一中构造器时, -你可以使用requierd变量来标记构造器,要求任意子类来重写它。指定类的构造器必须初始化类所有的已声明的属性, +正如在初始化声明(Initializer Declaration)谈及的那样,类可以有指定(designated)和方便(convenience)构造器。当你声明任一种构造器时, +你可以使用required变量来标记构造器,要求任意子类来重写它。指定类的构造器必须初始化类所有的已声明的属性, 它必须在子类构造器调用前被执行。 类可以重写属性,方法和它的超类的构造器。重写的方法和属性必须以override标注。