37
37
<a name =" stored_properties " ></a >
38
38
## 存储属性
39
39
40
- 简单来说,一个存储属性就是存储在特定类或结构体的实例里的一个常量或变量 。存储属性可以是* 变量存储属性* (用关键字 ` var ` 定义),也可以是* 常量存储属性* (用关键字 ` let ` 定义)。
40
+ 简单来说,一个存储属性就是存储在特定类或结构体实例里的一个常量或变量 。存储属性可以是* 变量存储属性* (用关键字 ` var ` 定义),也可以是* 常量存储属性* (用关键字 ` let ` 定义)。
41
41
42
42
可以在定义存储属性的时候指定默认值,请参考[ 默认构造器] ( ./14_Initialization.html#default_initializers ) 一节。也可以在构造过程中设置或修改存储属性的值,甚至修改常量存储属性的值,请参考[ 构造过程中常量属性的修改] ( ./14_Initialization.html#assigning_constant_properties_during_initialization ) 一节。
43
43
44
- 下面的例子定义了一个名为 ` FixedLengthRange ` 的结构体,它描述了一个在创建后无法修改值域宽度的区间 :
44
+ 下面的例子定义了一个名为 ` FixedLengthRange ` 的结构体,它描述了一个用于表示整型范围的常量,在创建后就不能进行修改 :
45
45
46
46
``` swift
47
47
struct FixedLengthRange {
@@ -59,7 +59,7 @@ rangeOfThreeItems.firstValue = 6
59
59
<a name =" stored_properties_of_constant_structure_instances " ></a >
60
60
### 常量结构体的存储属性
61
61
62
- 如果创建了一个结构体的实例并将其赋值给一个常量,则无法修改该实例的任何属性,即使定义了变量存储属性 :
62
+ 如果创建了一个结构体的实例并将其赋值给一个常量,则无法修改该实例的任何属性,即使有属性被声明为变量也不行 :
63
63
64
64
``` swift
65
65
let rangeOfFourItems = FixedLengthRange (firstValue : 0 , length : 4 )
@@ -82,9 +82,9 @@ rangeOfFourItems.firstValue = 6
82
82
> 注意
83
83
> 必须将延迟存储属性声明成变量(使用 ` var ` 关键字),因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。
84
84
85
- 延迟属性很有用,当属性的值依赖于在实例的构造过程结束后才会知道具体值的外部因素时 ,或者当获得属性的初始值需要复杂或大量计算时,可以只在需要的时候计算它。
85
+ 延迟属性很有用,当属性的值依赖于在实例的构造过程结束后才会知道影响值的外部因素时 ,或者当获得属性的初始值需要复杂或大量计算时,可以只在需要的时候计算它。
86
86
87
- 下面的例子使用了延迟存储属性来避免复杂类中不必要的初始化。例子中定义了 ` DataImporter ` 和 ` DataManager ` 两个类,下面是部分代码:
87
+ 下面的例子使用了延迟存储属性来避免复杂类中不必要的初始化。例子中定义了 ` DataImporter ` 和 ` DataManager ` 两个类,下面是部分代码:
88
88
89
89
``` swift
90
90
class DataImporter {
@@ -108,7 +108,7 @@ manager.data.append("Some more data")
108
108
// DataImporter 实例的 importer 属性还没有被创建
109
109
```
110
110
111
- ` DataManager ` 类包含一个名为` data ` 的存储属性,初始值是一个空的字符串(` String ` )数组。这里没有给出全部代码,只需知道 ` DataManager ` 类的目的是管理和提供对这个字符串数组的访问即可。
111
+ ` DataManager ` 类包含一个名为 ` data ` 的存储属性,初始值是一个空的字符串(` String ` )数组。这里没有给出全部代码,只需知道 ` DataManager ` 类的目的是管理和提供对这个字符串数组的访问即可。
112
112
113
113
` DataManager ` 的一个功能是从文件导入数据。该功能由 ` DataImporter ` 类提供,` DataImporter ` 完成初始化需要消耗不少时间:因为它的实例在初始化时可能要打开文件,还要读取文件内容到内存。
114
114
@@ -169,11 +169,11 @@ print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
169
169
170
170
这个例子定义了 3 个结构体来描述几何形状:
171
171
172
- - ` Point ` 封装了一个` (x, y) ` 的坐标
173
- - ` Size ` 封装了一个` width ` 和一个` height `
174
- - ` Rect ` 表示一个有原点和尺寸的矩形
172
+ - ` Point ` 封装了一个 ` (x, y) ` 的坐标
173
+ - ` Size ` 封装了一个 ` width ` 和一个 ` height `
174
+ - ` Rect ` 表示一个有原点和尺寸的矩形
175
175
176
- ` Rect ` 也提供了一个名为` center ` 的计算属性。一个矩形的中心点可以从原点(` origin ` )和尺寸 (` size ` )算出,所以不需要将它以显式声明的` Point ` 来保存。` Rect ` 的计算属性 ` center ` 提供了自定义的 getter 和 setter 来获取和设置矩形的中心点,就像它有一个存储属性一样。
176
+ ` Rect ` 也提供了一个名为` center ` 的计算属性。一个矩形的中心点可以从原点(` origin ` )和大小 (` size ` )算出,所以不需要将它以显式声明的 ` Point ` 来保存。` Rect ` 的计算属性 ` center ` 提供了自定义的 getter 和 setter 来获取和设置矩形的中心点,就像它有一个存储属性一样。
177
177
178
178
上述例子中创建了一个名为 ` square ` 的 ` Rect ` 实例,初始值原点是 ` (0, 0) ` ,宽度高度都是 ` 10 ` 。如下图中蓝色正方形所示。
179
179
@@ -233,12 +233,10 @@ print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
233
233
<a name =" property_observers " ></a >
234
234
## 属性观察器
235
235
236
- * 属性观察器* 监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,甚至新值和当前值相同的时候也不例外 。
236
+ * 属性观察器* 监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,即使新值和当前值相同的时候也不例外 。
237
237
238
- 可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重写属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。属性重写请参考[ 重写] ( ./13_Inheritance.html#overriding ) 。
238
+ 可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重写属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。你不必为非重写的计算属性添加属性观察器,因为可以通过它的 setter 直接监控和响应值的变化。 属性重写请参考[ 重写] ( ./13_Inheritance.html#overriding ) 。
239
239
240
- > 注意
241
- > 不需要为非重写的计算属性添加属性观察器,因为可以通过它的 setter 直接监控和响应值的变化。
242
240
243
241
可以为属性添加如下的一个或全部观察器:
244
242
@@ -247,13 +245,13 @@ print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
247
245
248
246
` willSet ` 观察器会将新的属性值作为常量参数传入,在 ` willSet ` 的实现代码中可以为这个参数指定一个名称,如果不指定则参数仍然可用,这时使用默认名称 ` newValue ` 表示。
249
247
250
- 类似地 ,` didSet ` 观察器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名 ` oldValue ` 。
248
+ 同样 ,` didSet ` 观察器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名 ` oldValue ` 。如果在 ` didSet ` 方法中再次对该属性赋值,那么新值会覆盖旧的值 。
251
249
252
250
> 注意
253
- > 父类的属性在子类的构造器中被赋值时,它在父类中的 ` willSet ` 和 ` didSet ` 观察器会被调用。
251
+ > 父类的属性在子类的构造器中被赋值时,它在父类中的 ` willSet ` 和 ` didSet ` 观察器会被调用,随后才会调用子类的观察器。在父类书初始化方法调用之前,子类给属性赋值时,观察器不会被调用。
254
252
> 有关构造器代理的更多信息,请参考[ 值类型的构造器代理] ( ./14_Initialization.html#initializer_delegation_for_value_types ) 和[ 类的构造器代理规则] ( ./14_Initialization.html#initializer_delegation_for_class_types ) 。
255
253
256
- 这里是一个 ` willSet ` 和 ` didSet ` 的实际例子 ,其中定义了一个名为 ` StepCounter ` 的类,用来统计一个人步行时的总步数。这个类可以跟计步器或其他日常锻炼的统计装置的输入数据配合使用。
254
+ 下面是一个 ` willSet ` 和 ` didSet ` 实际运用的例子 ,其中定义了一个名为 ` StepCounter ` 的类,用来统计一个人步行时的总步数。这个类可以跟计步器或其他日常锻炼的统计装置的输入数据配合使用。
257
255
258
256
``` swift
259
257
class StepCounter {
@@ -282,7 +280,7 @@ stepCounter.totalSteps = 896
282
280
283
281
` StepCounter ` 类定义了一个` Int ` 类型的属性 ` totalSteps ` ,它是一个存储属性,包含 ` willSet ` 和 ` didSet ` 观察器。
284
282
285
- 当 ` totalSteps ` 被设置新值的时候,它的 ` willSet ` 和 ` didSet ` 观察器都会被调用,甚至新值和当前值完全相同时也会被调用 。
283
+ 当 ` totalSteps ` 被设置新值的时候,它的 ` willSet ` 和 ` didSet ` 观察器都会被调用,即使新值和当前值完全相同时也会被调用 。
286
284
287
285
例子中的 ` willSet ` 观察器将表示新值的参数自定义为 ` newTotalSteps ` ,这个观察器只是简单的将新的值输出。
288
286
0 commit comments