去除行末冗余空格
This commit is contained in:
@@ -14,11 +14,11 @@
|
||||
|
||||
> 2.2
|
||||
> 翻译:[pmst](https://github.com/colourful987)
|
||||
> 翻译+校对:[SketchK](https://github.com/SketchK) 2016-05-14
|
||||
> 翻译+校对:[SketchK](https://github.com/SketchK) 2016-05-14
|
||||
> 3.0.1,shanks,2016-11-13
|
||||
|
||||
> 3.1
|
||||
> 翻译:[qhd](https://github.com/qhd) 2017-04-18
|
||||
> 翻译:[qhd](https://github.com/qhd) 2017-04-18
|
||||
|
||||
> 4.0
|
||||
> 翻译:[muhlenXi](https://github.com/muhlenxi) 2017-09-21
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
你可以在构造器中为存储型属性赋初值,也可以在定义属性时为其设置默认值。以下小节将详细介绍这两种方法。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
当你为存储型属性设置默认值或者在构造器中为其赋值时,它们的值是被直接设置的,不会触发任何属性观察者。
|
||||
|
||||
<a name="initializers"></a>
|
||||
@@ -82,7 +82,7 @@ print("The default temperature is \(f.temperature)° Fahrenheit")
|
||||
|
||||
如前所述,你可以在构造器中为存储型属性设置初始值。同样,你也可以在属性声明时为其设置默认值。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
如果一个属性总是使用相同的初始值,那么为其设置一个默认值比每次都在构造器中赋值要好。两种方法的效果是一样的,只不过使用默认值让属性的初始化和声明结合得更紧密。使用默认值能让你的构造器更简洁、更清晰,且能通过默认值自动推导出属性的类型;同时,它也能让你充分利用默认构造器、构造器继承等特性,后续章节将讲到。
|
||||
|
||||
你可以使用更简单的方式在定义结构体 `Fahrenheit` 时为属性 `temperature` 设置默认值:
|
||||
@@ -224,7 +224,7 @@ cheeseQuestion.response = "Yes, I do like cheese."
|
||||
|
||||
你可以在构造过程中的任意时间点给常量属性指定一个值,只要在构造过程结束时是一个确定的值。一旦常量属性被赋值,它将永远不可更改。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
对于类的实例来说,它的常量属性只能在定义它的类的构造过程中修改;不能在子类中修改。
|
||||
|
||||
你可以修改上面的 `SurveyQuestion` 示例,用常量属性替代变量属性 `text`,表示问题内容 `text` 在`SurveyQuestion`的实例被创建之后不会再被修改。尽管 `text` 属性现在是常量,我们仍然可以在类的构造器中设置它的值:
|
||||
@@ -293,7 +293,7 @@ let twoByTwo = Size(width: 2.0, height: 2.0)
|
||||
|
||||
请注意,如果你为某个值类型定义了一个自定义的构造器,你将无法访问到默认构造器(如果是结构体,还将无法访问逐一成员构造器)。这种限制可以防止你为值类型增加了一个额外的且十分复杂的构造器之后,仍然有人错误的使用自动生成的构造器
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
假如你希望默认构造器、逐一成员构造器以及你自己的自定义构造器都能用来创建实例,可以将自定义的构造器写到扩展(`extension`)中,而不是写在值类型的原始定义中。想查看更多内容,请查看[扩展](./21_Extensions.html)章节。
|
||||
|
||||
下面例子将定义一个结构体 `Rect`,用来代表几何矩形。这个例子需要两个辅助的结构体 `Size` 和 `Point`,它们各自为其所有的属性提供了默认初始值 `0.0`。
|
||||
@@ -354,7 +354,7 @@ let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
|
||||
|
||||
构造器 `init(center:size:)` 可以直接将 `origin` 和 `size` 的新值赋值到对应的属性中。然而,构造器 `init(center:size:)` 通过使用提供了相关功能的现有构造器将会更加便捷。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
如果你想用另外一种不需要自己定义`init()`和`init(origin:size:)`的方式来实现这个例子,请参考[扩展](./21_Extensions.html)。
|
||||
|
||||
<a name="class_inheritance_and_initialization"></a>
|
||||
@@ -426,7 +426,7 @@ convenience init(parameters) {
|
||||
|
||||
子类中包含两个指定构造器和一个便利构造器。便利构造器必须调用两个指定构造器中的任意一个,因为它只能调用同一个类里的其他构造器。这满足了上面提到的规则 2 和 3。而两个指定构造器必须调用父类中唯一的指定构造器,这满足了规则 1。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
这些规则不会影响类的实例如何创建。任何上图中展示的构造器都可以用来创建完全初始化的实例。这些规则只影响类的构造器如何实现。
|
||||
|
||||
下面图例中展示了一种涉及四个类的更复杂的类层级结构。它演示了指定构造器是如何在类层级中充当“管道”的作用,在类的构造器链上简化了类之间的相互关系。
|
||||
@@ -440,7 +440,7 @@ Swift 中类的构造过程包含两个阶段。第一个阶段,类中的每
|
||||
|
||||
两段式构造过程的使用让构造过程更安全,同时在整个类层级结构中给予了每个类完全的灵活性。两段式构造过程可以防止属性值在初始化之前被访问,也可以防止属性被另外一个构造器意外地赋予不同的值。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
Swift 的两段式构造过程跟 Objective-C 中的构造过程类似。最主要的区别在于阶段 1,Objective-C 给每一个属性赋值 `0` 或空值(比如说`0`或`nil`)。Swift 的构造流程则更加灵活,它允许你设置定制的初始值,并自如应对某些属性不能以 `0` 或 `nil` 作为合法默认值的情况。
|
||||
|
||||
Swift 编译器将执行 4 种有效的安全检查,以确保两段式构造过程不出错地完成:
|
||||
@@ -508,7 +508,7 @@ Swift 编译器将执行 4 种有效的安全检查,以确保两段式构造
|
||||
|
||||
跟 Objective-C 中的子类不同,Swift 中的子类默认情况下不会继承父类的构造器。Swift 的这种机制可以防止一个父类的简单构造器被一个更精细的子类继承,并被错误地用来创建子类的实例。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
父类的构造器仅会在安全和适当的情况下被继承。具体内容请参考后续章节[构造器的自动继承](#automatic_initializer_inheritance)。
|
||||
|
||||
假如你希望自定义的子类中能提供一个或多个跟父类相同的构造器,你可以在子类中提供这些构造器的自定义实现。
|
||||
@@ -517,7 +517,7 @@ Swift 编译器将执行 4 种有效的安全检查,以确保两段式构造
|
||||
|
||||
正如重写属性,方法或者是下标,`override` 修饰符会让编译器去检查父类中是否有相匹配的指定构造器,并验证构造器参数是否正确。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
当你重写一个父类的指定构造器时,你总是需要写`override`修饰符,即使是为了实现子类的便利构造器。
|
||||
|
||||
相反,如果你编写了一个和父类便利构造器相匹配的子类构造器,由于子类不能直接调用父类的便利构造器(每个规则都在上文[类的构造器代理规则](#initializer_delegation_for_class_types)有所描述),因此,严格意义上来讲,你的子类并未对一个父类构造器提供重写。最后的结果就是,你在子类中“重写”一个父类便利构造器时,不需要加 `override` 修饰符。
|
||||
@@ -565,7 +565,7 @@ print("Bicycle: \(bicycle.description)")
|
||||
// 打印 "Bicycle: 2 wheel(s)"
|
||||
```
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
子类可以在初始化时修改继承来的变量属性,但是不能修改继承来的常量属性。
|
||||
|
||||
<a name="automatic_initializer_inheritance"></a>
|
||||
@@ -585,7 +585,7 @@ print("Bicycle: \(bicycle.description)")
|
||||
|
||||
即使你在子类中添加了更多的便利构造器,这两条规则仍然适用。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
对于规则 2,子类可以将父类的指定构造器实现为便利构造器。
|
||||
|
||||
<a name="designated_and_convenience_initializers_in_action"></a>
|
||||
@@ -680,7 +680,7 @@ class ShoppingListItem: RecipeIngredient {
|
||||
}
|
||||
```
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
`ShoppingListItem` 没有定义构造器来为 `purchased` 提供初始值,因为添加到购物单的物品的初始状态总是未购买。
|
||||
|
||||
由于它为自己引入的所有属性都提供了默认值,并且自己没有定义任何构造器,`ShoppingListItem` 将自动继承所有父类中的指定构造器和便利构造器。
|
||||
@@ -716,15 +716,15 @@ for item in breakfastList {
|
||||
|
||||
为了妥善处理这种构造过程中可能会失败的情况。你可以在一个类,结构体或是枚举类型的定义中,添加一个或多个可失败构造器。其语法为在 `init` 关键字后面添加问号 (`init?`)。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
可失败构造器的参数名和参数类型,不能与其它非可失败构造器的参数名,及其参数类型相同。
|
||||
|
||||
可失败构造器会创建一个类型为自身类型的可选类型的对象。你通过 `return nil` 语句来表明可失败构造器在何种情况下应该 “失败”。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
严格来说,构造器都不支持返回值。因为构造器本身的作用,只是为了确保对象能被正确构造。因此你只是用`return nil`表明可失败构造器构造失败,而不要用关键字`return`来表明构造成功。
|
||||
|
||||
例如,实现针对数字类型转换的可失败构造器。确保数字类型之间的转换能保持精确的值,使用这个 `init(exactly:)` 构造器。如果类型转换不能保持值不变,则这个构造器构造失败。
|
||||
例如,实现针对数字类型转换的可失败构造器。确保数字类型之间的转换能保持精确的值,使用这个 `init(exactly:)` 构造器。如果类型转换不能保持值不变,则这个构造器构造失败。
|
||||
|
||||
```
|
||||
let wholeNumber: Double = 12345.0
|
||||
@@ -781,7 +781,7 @@ if anonymousCreature == nil {
|
||||
// 打印 "The anonymous creature could not be initialized"
|
||||
```
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
空字符串(如 `""`,而不是 `"Giraffe"` )和一个值为 `nil` 的可选类型的字符串是两个完全不同的概念。上例中的空字符串(`""`)其实是一个有效的,非可选类型的字符串。这里我们之所以让 `Animal` 的可失败构造器构造失败,只是因为对于 `Animal` 这个类的 `species` 属性来说,它更适合有一个具体的值,而不是空字符串。
|
||||
|
||||
<a name="failable_nitializers_for_enumerations"></a>
|
||||
@@ -857,7 +857,7 @@ if unknownUnit == nil {
|
||||
|
||||
无论是向上代理还是横向代理,如果你代理到的其他可失败构造器触发构造失败,整个构造过程将立即终止,接下来的任何构造代码不会再被执行。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
可失败构造器也可以代理到其它的非可失败构造器。通过这种方式,你可以增加一个可能的失败状态到现有的构造过程中。
|
||||
|
||||
下面这个例子,定义了一个名为`CartItem`的`Product`类的子类。这个类建立了一个在线购物车中的物品的模型,它有一个名为`quantity`的常量存储型属性,并确保该属性的值至少为`1`:
|
||||
@@ -865,7 +865,7 @@ if unknownUnit == nil {
|
||||
```swift
|
||||
class Product {
|
||||
let name: String
|
||||
init?(name: String) {
|
||||
init?(name: String) {
|
||||
if name.isEmpty { return nil }
|
||||
self.name = name
|
||||
}
|
||||
@@ -901,7 +901,7 @@ if let zeroShirts = CartItem(name: "shirt", quantity: 0) {
|
||||
print("Unable to initialize zero shirts")
|
||||
}
|
||||
// 打印 "Unable to initialize zero shirts"
|
||||
```
|
||||
```
|
||||
|
||||
同样地,如果你尝试传入一个值为空字符串的 `name` 来创建一个 `CartItem` 实例,那么将导致父类 `Product` 的构造过程失败:
|
||||
|
||||
@@ -921,7 +921,7 @@ if let oneUnnamed = CartItem(name: "", quantity: 1) {
|
||||
|
||||
注意,当你用子类的非可失败构造器重写父类的可失败构造器时,向上代理到父类的可失败构造器的唯一方式是对父类的可失败构造器的返回值进行强制解包。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
你可以用非可失败构造器重写可失败构造器,但反过来却不行。
|
||||
|
||||
下例定义了一个名为 `Document` 的类,`name` 属性的值必须为一个非空字符串或 `nil`,但不能是一个空字符串:
|
||||
@@ -1002,7 +1002,7 @@ class SomeSubclass: SomeClass {
|
||||
}
|
||||
```
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
如果子类继承的构造器能满足必要构造器的要求,则无须在子类中显式提供必要构造器的实现。
|
||||
|
||||
<a name="setting_a_default_property_value_with_a_closure_or_function"></a>
|
||||
@@ -1026,7 +1026,7 @@ class SomeClass {
|
||||
|
||||
注意闭包结尾的花括号后面接了一对空的小括号。这用来告诉 Swift 立即执行此闭包。如果你忽略了这对括号,相当于将闭包本身作为值赋值给了属性,而不是将闭包的返回值赋值给属性。
|
||||
|
||||
> 注意
|
||||
> 注意
|
||||
如果你使用闭包来初始化属性,请记住在闭包执行时,实例的其它部分都还没有初始化。这意味着你不能在闭包里访问其它属性,即使这些属性有默认值。同样,你也不能使用隐式的 `self` 属性,或者调用任何实例方法。
|
||||
|
||||
下面例子中定义了一个结构体 `Chessboard`,它构建了西洋跳棋游戏的棋盘,西洋跳棋游戏在一副黑白格交替的 8 x 8 的棋盘中进行的:
|
||||
|
||||
Reference in New Issue
Block a user