2
2
3
3
通过子类化来添加或重写功能。
4
4
5
- 一个类可以从另一个类* 继承* 方法、属性和其他特性。
6
- 当一个类从另一个类继承时,继承的类被称为* 子类* ,
7
- 而被它继承的类被称为* 父类* 。
8
- 继承是 Swift 中区别类与其他类型的基本特性。
5
+ 一个类可以从另一个类* 继承* 方法、属性和其他特性。当一个类从另一个类继承时,继承的类被称为* 子类* ,而被它继承的类被称为* 父类* 。继承是 Swift 中区别类与其他类型的基本特性。
9
6
10
- Swift 中的类可以调用和访问属于其父类的方法、属性和下标,
11
- 并且可以通过重写这些方法、属性和下标来优化或修改他们的行为。
12
- Swift 通过检查重写定义是否与父类定义相匹配来帮助确保您的覆盖是正确的。
7
+ Swift 中的类可以调用和访问属于其父类的方法、属性和下标,并且可以通过重写这些方法、属性和下标来优化或修改他们的行为。Swift 通过检查重写定义是否与父类定义相匹配来帮助确保您的覆盖是正确的。
13
8
14
- 类还可以为继承的属性添加属性观察器,以便在属性值发生变化时得到通知。
15
- 无论最初是定义为存储属性还是计算属性,都可以为任何属性添加属性观察器。
9
+ 类还可以为继承的属性添加属性观察器,以便在属性值发生变化时得到通知。无论最初是定义为存储属性还是计算属性,都可以为任何属性添加属性观察器。
16
10
17
11
## 定义基类
18
12
19
13
任何没有被继承的类都被称作基类。
20
14
21
- > 注意: Swift 中没有统一的基类,所有类的起源都是平等的。
22
- > 您不指定父类的类会自动成为基类。
15
+ > 注意: Swift 中没有统一的基类,所有类的起源都是平等的。您不指定父类的类会自动成为基类。
23
16
24
- 下面的示例定义了一个名为 ` Vehicle ` 的基类。
25
- 这个基类定义了一个名为 ` currentSpeed ` 的存储属性,默认值为 ` 0.0 ` (推断出属性类型为 ` Double ` )。
26
- ` currentSpeed ` 属性的值被一个只读计算 ` String ` 属性 ` description ` 用于创建车辆的描述。
17
+ 下面的示例定义了一个名为 ` Vehicle ` 的基类。这个基类定义了一个名为 ` currentSpeed ` 的存储属性,默认值为 ` 0.0 ` (推断出属性类型为 ` Double ` )。` currentSpeed ` 属性的值被一个只读计算 ` String ` 属性 ` description ` 用于创建车辆的描述。
27
18
28
- ` Vehicle ` 基类还定义了一个名为 ` makeNoise() ` 的方法。
29
- 这个方法对于基类 Vehicle 的实例不会做任何事情,但稍后会被 ` Vehicle ` 的子类自定义:
19
+ ` Vehicle ` 基类还定义了一个名为 ` makeNoise() ` 的方法。这个方法对于基类 Vehicle 的实例不会做任何事情,但稍后会被 ` Vehicle ` 的子类自定义:
30
20
31
21
``` swift
32
22
class Vehicle {
@@ -70,8 +60,7 @@ let someVehicle = Vehicle()
70
60
```
71
61
-->
72
62
73
- 创建了一个新的 ` Vehicle ` 实例后,
74
- 您可以访问它的 ` description ` 属性来打印车辆当前速度的描述:
63
+ 创建了一个新的 ` Vehicle ` 实例后,您可以访问它的 ` description ` 属性来打印车辆当前速度的描述:
75
64
76
65
``` swift
77
66
print (" Vehicle: \( someVehicle.description ) " )
@@ -87,14 +76,11 @@ print("Vehicle: \(someVehicle.description)")
87
76
```
88
77
-->
89
78
90
- ` Vehicle ` 类定义了任意车辆的通用特性,但本身并不太有用。
91
- 要使其更有用,您需要对其进行完善以描述更具体的车辆类型。
79
+ ` Vehicle ` 类定义了任意车辆的通用特性,但本身并不太有用。要使其更有用,您需要对其进行完善以描述更具体的车辆类型。
92
80
93
81
## 子类化
94
82
95
- * 子类化* 是基于现有类创建新类的行为。
96
- 子类继承现有类的特性,然后您可以对其进行完善。
97
- 您还可以向子类添加新的特性。
83
+ * 子类化* 是基于现有类创建新类的行为。子类继承现有类的特性,然后您可以对其进行完善。您还可以向子类添加新的特性。
98
84
99
85
要指示子类有一个父类,请在父类名前写子类名,中间用冒号分隔:
100
86
@@ -133,14 +119,11 @@ class Bicycle: Vehicle {
133
119
```
134
120
-->
135
121
136
- 新的 ` Bicycle ` 类自动获得了 ` Vehicle ` 的所有特性,
137
- 例如它的 ` currentSpeed ` 和 ` description ` 属性以及 ` makeNoise() ` 方法。
122
+ 新的 ` Bicycle ` 类自动获得了 ` Vehicle ` 的所有特性,例如它的 ` currentSpeed ` 和 ` description ` 属性以及 ` makeNoise() ` 方法。
138
123
139
- 除了继承的特性之外,` Bicycle ` 类还定义了一个新的存储属性 ` hasBasket ` ,
140
- 默认值为 ` false ` (推断该属性的类型为 ` Bool ` )。
124
+ 除了继承的特性之外,` Bicycle ` 类还定义了一个新的存储属性 ` hasBasket ` ,默认值为 ` false ` (推断该属性的类型为 ` Bool ` )。
141
125
142
- 默认情况下,您创建的任何新 ` Bicycle ` 实例都默认没有篮子。
143
- 在创建实例后,您可以将特定 ` Bicycle ` 实例的 ` hasBasket ` 属性设置为 ` true ` :
126
+ 默认情况下,您创建的任何新 ` Bicycle ` 实例都默认没有篮子。在创建实例后,您可以将特定 ` Bicycle ` 实例的 ` hasBasket ` 属性设置为 ` true ` :
144
127
145
128
``` swift
146
129
let bicycle = Bicycle ()
@@ -156,8 +139,7 @@ bicycle.hasBasket = true
156
139
```
157
140
-->
158
141
159
- 您还可以修改 ` Bicycle ` 实例继承的 ` currentSpeed ` 属性,
160
- 并查询实例继承的 ` description ` 属性:
142
+ 您还可以修改 ` Bicycle ` 实例继承的 ` currentSpeed ` 属性,并查询实例继承的 ` description ` 属性:
161
143
162
144
``` swift
163
145
bicycle.currentSpeed = 15.0
@@ -175,8 +157,7 @@ print("Bicycle: \(bicycle.description)")
175
157
```
176
158
-->
177
159
178
- 子类本身也可以被子类化。下一个示例创建了一个 ` Bicycle ` 的子类,
179
- 用于双人自行车,称为 “tandem”:
160
+ 子类本身也可以被子类化。下一个示例创建了一个 ` Bicycle ` 的子类,用于双人自行车,称为 “tandem”:
180
161
181
162
``` swift
182
163
class Tandem : Bicycle {
@@ -194,12 +175,9 @@ class Tandem: Bicycle {
194
175
```
195
176
-->
196
177
197
- ` Tandem ` 继承了 ` Bicycle ` 的所有属性和方法,
198
- 而 ` Bicycle ` 又继承了 ` Vehicle ` 的所有属性和方法。
199
- ` Tandem ` 子类还添加了一个名为 ` currentNumberOfPassengers ` 的新存储属性,默认值为 ` 0 ` 。
178
+ ` Tandem ` 继承了 ` Bicycle ` 的所有属性和方法,而 ` Bicycle ` 又继承了 ` Vehicle ` 的所有属性和方法。` Tandem ` 子类还添加了一个名为 ` currentNumberOfPassengers ` 的新存储属性,默认值为 ` 0 ` 。
200
179
201
- 如果您创建一个 ` Tandem ` 实例,您可以使用它的任何新属性和继承的属性,
202
- 并查询它从 ` Vehicle ` 继承的只读属性:` description `
180
+ 如果您创建一个 ` Tandem ` 实例,您可以使用它的任何新属性和继承的属性,并查询它从 ` Vehicle ` 继承的只读属性:` description `
203
181
204
182
``` swift
205
183
let tandem = Tandem ()
@@ -225,39 +203,27 @@ print("Tandem: \(tandem.description)")
225
203
226
204
## 重写
227
205
228
- 子类可以提供自己的自定义实现来覆盖它将从父类继承的实例方法、
229
- 类型方法、实例属性、类型属性或下标。这被称为* 重写* 。
206
+ 子类可以提供自己的自定义实现来覆盖它将从父类继承的实例方法、类型方法、实例属性、类型属性或下标。这被称为* 重写* 。
230
207
231
- 要重写将被继承的特性,您需要在重写定义前加上 ` override ` 关键字。
232
- 这样做可以明确您打算提供重写,而不是由于疏忽而提供了相同的定义。
233
- 无意间的重写可能会导致意外行为,任何没有 ` override ` 关键字的重写
234
- 在编译代码时都会被诊断为错误。
208
+ 要重写将被继承的特性,您需要在重写定义前加上 ` override ` 关键字。这样做可以明确您打算提供重写,而不是由于疏忽而提供了相同的定义。无意间的重写可能会导致意外行为,任何没有 ` override ` 关键字的重写在编译代码时都会被诊断为错误。
235
209
236
- ` override ` 关键字还会提示 Swift 编译器检查您的重写类的父类
237
- (或其父类之一)是否有与您提供的重写定义相匹配的声明。
238
- 这个检查可以确保您的重写定义是正确的。
210
+ ` override ` 关键字还会提示 Swift 编译器检查您的重写类的父类(或其父类之一)是否有与您提供的重写定义相匹配的声明。这个检查可以确保您的重写定义是正确的。
239
211
240
212
### 访问父类方法、属性和下标
241
213
242
- 当您为子类提供方法、属性或下标重写时,
243
- 有时使用现有父类实现作为重写的一部分是很有用的。
244
- 例如,您可以改进现有实现的行为,或在现有继承的变量中存储修改后的值。
214
+ 当您为子类提供方法、属性或下标重写时,有时使用现有父类实现作为重写的一部分是很有用的。例如,您可以改进现有实现的行为,或在现有继承的变量中存储修改后的值。
245
215
246
216
在适当的情况下,您可以使用 ` super ` 前缀来访问父类的方法、属性或下标:
247
217
248
- - 一个被重写的名为 ` someMethod() ` 的方法可以在重写方法实现中
249
- 通过调用 ` super.someMethod() ` 来调用父类版本的 ` someMethod() ` 。
250
- - 一个被重写的名为 ` someProperty ` 的属性可以在重写的 getter 或 setter 实现中
251
- 通过 ` super.someProperty ` 来访问父类版本的 ` someProperty ` 。
252
- - 一个被重写的针对 ` someIndex ` 的下标可以在重写的下标实现中
253
- 通过 ` super[someIndex] ` 来访问同一下标的父类版本。
218
+ - 一个被重写的名为 ` someMethod() ` 的方法可以在重写方法实现中通过调用 ` super.someMethod() ` 来调用父类版本的 ` someMethod() ` 。
219
+ - 一个被重写的名为 ` someProperty ` 的属性可以在重写的 getter 或 setter 实现中通过 ` super.someProperty ` 来访问父类版本的 ` someProperty ` 。
220
+ - 一个被重写的针对 ` someIndex ` 的下标可以在重写的下标实现中通过 ` super[someIndex] ` 来访问同一下标的父类版本。
254
221
255
222
### 重写方法
256
223
257
224
您可以重写继承的实例或类型方法,以在子类中提供该方法的定制或替代实现。
258
225
259
- 下面的示例定义了一个名为 ` Train ` 的新 ` Vehicle ` 子类,
260
- 它重写了从 ` Vehicle ` 继承的 ` makeNoise() ` 方法:
226
+ 下面的示例定义了一个名为 ` Train ` 的新 ` Vehicle ` 子类,它重写了从 ` Vehicle ` 继承的 ` makeNoise() ` 方法:
261
227
262
228
``` swift
263
229
class Train : Vehicle {
@@ -279,8 +245,7 @@ class Train: Vehicle {
279
245
```
280
246
-->
281
247
282
- 如果您创建一个新的 ` Train ` 实例并调用它的 ` makeNoise() ` 方法,
283
- 您可以看到调用了 ` Train ` 子类版本的方法:
248
+ 如果您创建一个新的 ` Train ` 实例并调用它的 ` makeNoise() ` 方法,您可以看到调用了 ` Train ` 子类版本的方法:
284
249
285
250
``` swift
286
251
let train = Train ()
@@ -300,31 +265,17 @@ train.makeNoise()
300
265
301
266
### 重写属性
302
267
303
- 您可以重写继承的实例或类型属性,
304
- 为该属性提供自己的自定义 getter 和 setter,
305
- 或添加属性观察器以使重写的属性能够观察底层属性值的变化。
268
+ 您可以重写继承的实例或类型属性,为该属性提供自己的自定义 getter 和 setter,或添加属性观察器以使重写的属性能够观察底层属性值的变化。
306
269
307
270
#### 重写属性 Getter 和 Setter
308
271
309
- 您可以为任何继承的属性提供自定义 getter(如果需要的话还有 setter),
310
- 无论继承的属性在源码中是作为存储属性还是计算属性实现的。
311
- 子类不知道继承属性的存储或计算性质,
312
- 它只知道继承的属性有一个特定的名称和类型。
313
- 您必须始终声明要重写的属性的名称和类型,
314
- 以便编译器检查您的重写与父类中具有相同名称和类型的属性相匹配。
272
+ 您可以为任何继承的属性提供自定义 getter(如果需要的话还有 setter),无论继承的属性在源码中是作为存储属性还是计算属性实现的。子类不知道继承属性的存储或计算性质,它只知道继承的属性有一个特定的名称和类型。您必须始终声明要重写的属性的名称和类型,以便编译器检查您的重写与父类中具有相同名称和类型的属性相匹配。
315
273
316
- 您可以通过在子类属性重写中提供 getter 和 setter 来将继承的只读属性表示为可读写属性。
317
- 但是您不能将继承的可读写属性声明为只读属性。
274
+ 您可以通过在子类属性重写中提供 getter 和 setter 来将继承的只读属性表示为可读写属性。但是您不能将继承的可读写属性声明为只读属性。
318
275
319
- > 如果您在属性重写中提供了 setter,您也必须为该重写提供 getter。
320
- > 如果您不想在重写的 getter 中修改继承属性的值。
321
- > 您可以简单地通过从 getter 返回 ` super.someProperty ` 来传递继承的值。
322
- > 其中 ` someProperty ` 是您正在重写的属性的名称。
276
+ > 如果您在属性重写中提供了 setter,您也必须为该重写提供 getter。如果您不想在重写的 getter 中修改继承属性的值。您可以简单地通过从 getter 返回 ` super.someProperty ` 来传递继承的值。其中 ` someProperty ` 是您正在重写的属性的名称。
323
277
324
- 下面的示例定义了一个名为 ` Car ` 的新类,它是 ` Vehicle ` 的子类。
325
- ` Car ` 类引入了一个名为 ` gear ` 的新存储属性,默认整数值为 ` 1 ` 。
326
- ` Car ` 类还重写了它从 ` Vehicle ` 继承的 ` description ` 属性,
327
- 以提供包含当前档位的自定义描述:
278
+ 下面的示例定义了一个名为 ` Car ` 的新类,它是 ` Vehicle ` 的子类。` Car ` 类引入了一个名为 ` gear ` 的新存储属性,默认整数值为 ` 1 ` 。` Car ` 类还重写了它从 ` Vehicle ` 继承的 ` description ` 属性,以提供包含当前档位的自定义描述:
328
279
329
280
``` swift
330
281
class Car : Vehicle {
@@ -348,13 +299,9 @@ class Car: Vehicle {
348
299
```
349
300
-->
350
301
351
- ` description ` 属性的重写首先调用 ` super.description ` ,
352
- 它返回 ` Vehicle ` 类的 ` description ` 属性。
353
- 然后,` Car ` 类的 ` description ` 版本在此描述的末尾添加了一些额外文本,
354
- 以提供有关当前档位的信息。
302
+ ` description ` 属性的重写首先调用 ` super.description ` ,它返回 ` Vehicle ` 类的 ` description ` 属性。然后,` Car ` 类的 ` description ` 版本在此描述的末尾添加了一些额外文本,以提供有关当前档位的信息。
355
303
356
- 如果您创建 ` Car ` 类的实例并设置其 ` gear ` 和 ` currentSpeed ` 属性,
357
- 您可以看到它的 ` description ` 属性返回在 ` Car ` 类中定义的定制描述:
304
+ 如果您创建 ` Car ` 类的实例并设置其 ` gear ` 和 ` currentSpeed ` 属性,您可以看到它的 ` description ` 属性返回在 ` Car ` 类中定义的定制描述:
358
305
359
306
``` swift
360
307
let car = Car ()
@@ -378,20 +325,13 @@ print("Car: \(car.description)")
378
325
379
326
#### 重写属性观察器
380
327
381
- 您可以使用属性重写的方式为继承的属性添加属性观察器。
382
- 这样无论该属性最初是如何实现的,您都能够在继承属性的值发生变化时得到通知。
383
- 有关属性观察器的更多信息,请参阅 < doc:Properties#Property-Observers > 。
328
+ 您可以使用属性重写的方式为继承的属性添加属性观察器。这样无论该属性最初是如何实现的,您都能够在继承属性的值发生变化时得到通知。有关属性观察器的更多信息,请参阅 < doc:Properties#Property-Observers > 。
384
329
385
- > 注意: 你无法为继承的常量存储属性或继承的只读计算属性添加属性观察器。
386
- > 这些属性的值无法被修改,所以在重写时提供 ` willSet ` 或 ` didSet ` 实现是不合适的。
330
+ > 注意: 你无法为继承的常量存储属性或继承的只读计算属性添加属性观察器。这些属性的值无法被修改,所以在重写时提供 ` willSet ` 或 ` didSet ` 实现是不合适的。
387
331
>
388
- > 另请注意,你不能为同一属性提供重写的 setter 和重写的属性观察器。
389
- > 如果你想观察属性值的变化,并且你已经为该属性提供了自定义 setter,
390
- > 你可以简单地在自定义 setter 中观察任何值的变化。
332
+ > 另请注意,你不能为同一属性提供重写的 setter 和重写的属性观察器。如果你想观察属性值的变化,并且你已经为该属性提供了自定义 setter,你可以简单地在自定义 setter 中观察任何值的变化。
391
333
392
- 以下示例创建了一个名为 ` AutomaticCar ` 的新类,它继承自 ` Car ` 类。
393
- ` AutomaticCar ` 类表示一辆带有自动变速箱的汽车,
394
- 根据当前速度自动选择合适的挡位:
334
+ 以下示例创建了一个名为 ` AutomaticCar ` 的新类,它继承自 ` Car ` 类。` AutomaticCar ` 类表示一辆带有自动变速箱的汽车,根据当前速度自动选择合适的挡位:
395
335
396
336
``` swift
397
337
class AutomaticCar : Car {
@@ -417,11 +357,7 @@ class AutomaticCar: Car {
417
357
```
418
358
-->
419
359
420
- 每当你设置 ` AutomaticCar ` 实例的 ` currentSpeed ` 属性时,
421
- 该属性的 ` didSet ` 观察器会根据新速度为实例的 ` gear ` 属性设置一个合适的挡位。
422
- 具体来说,属性观察器选择一个挡位,
423
- 该挡位是新 ` currentSpeed ` 值除以 10 向下取整后加 1。
424
- 速度为 ` 35.0 ` 时会挂 ` 4 ` 挡:
360
+ 每当你设置 ` AutomaticCar ` 实例的 ` currentSpeed ` 属性时,该属性的 ` didSet ` 观察器会根据新速度为实例的 ` gear ` 属性设置一个合适的挡位。具体来说,属性观察器选择一个挡位,该挡位是新 ` currentSpeed ` 值除以 10 向下取整后加 1。速度为 ` 35.0 ` 时会挂 ` 4 ` 挡:
425
361
426
362
``` swift
427
363
let automatic = AutomaticCar ()
@@ -443,14 +379,10 @@ print("AutomaticCar: \(automatic.description)")
443
379
444
380
## 防止重写
445
381
446
- 你可以通过将其标记为 * final* 来防止方法、属性或下标被重写。
447
- 在方法、属性或下标的引入关键字前写 ` final ` 修饰符。
448
- (如 ` final var ` 、` final func ` 、` final class func ` 和 ` final subscript ` )
382
+ 你可以通过将其标记为 * final* 来防止方法、属性或下标被重写。在方法、属性或下标的引入关键字前写 ` final ` 修饰符。(如 ` final var ` 、` final func ` 、` final class func ` 和 ` final subscript ` )
449
383
450
384
451
- 任何尝试在子类中重写 final 方法、属性或下标的行为都会在编译时报错。
452
- 你在扩展中添加到类的方法、属性或下标也可以在扩展的定义中标记为 final。
453
- 有关更多信息,请参阅 < doc:Extensions > 。
385
+ 任何尝试在子类中重写 final 方法、属性或下标的行为都会在编译时报错。你在扩展中添加到类的方法、属性或下标也可以在扩展的定义中标记为 final。有关更多信息,请参阅 < doc:Extensions > 。
454
386
455
387
<!--
456
388
- test: `finalPreventsOverriding`
@@ -486,9 +418,7 @@ print("AutomaticCar: \(automatic.description)")
486
418
```
487
419
-->
488
420
489
- 你可以通过在类定义(` final class ` )中在 ` class ` 关键字前
490
- 写 ` final ` 修饰符来将整个类标记为 final。
491
- 任何尝试子类化 final 类的行为都会在编译时报错。
421
+ 你可以通过在类定义(` final class ` )中在 ` class ` 关键字前写 ` final ` 修饰符来将整个类标记为 final。任何尝试子类化 final 类的行为都会在编译时报错。
492
422
493
423
<!--
494
424
- test: `finalClassPreventsOverriding`
0 commit comments