继承
类可以从另一个类继承方法、属性和其他特性,继承类称为子类,被继承类为其超类。Swift的类可以调用和访问超类的方法、属性和下标,并能重写这些版本以改进或修改其行为。
类还可以将属性观察器添加到继承的属性,属性观察器可以添加到任何属性。
## 定义基类 基类是不继承任何一个类的类。
注意
Swift类不会从通用基类继承,未指定超类的自定义类自动成为基类。
以下为一个自定义Vehicle基类:
class Vehicle {
var currentSpeed = 0.0
var description: String {
return "traveling at (currentSpeed) miles per hour"
}
func makeNoise() {
// do nothing - an arbitrary vehicle doesn't necessarily make a noise
}
}
使用初始化器语法创建一个类实例:
let someVehicle = Vehicle()
访问其description属性:
print("Vehicle: (someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour
## 子类化 子类化是将一个新类置于现有类之上的行为,子类继承现有类的特性,也可以向子类添加新特性。
继承语法如下:
class SomeSubclass: SomeSuperclass {
// subclass definition goes here
}
子类化Vehicle类:
class Bicycle: Vehicle {
var hasBasket = false
}
let bicycle = Bicycle()
bicycle.hasBasket = true
bicycle.currentSpeed = 15.0
print("Bicycle: (bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour
子类继续子类化:
class Tandem: Bicycle {
var currentNumberOfPassengers = 0
}
let tandem = Tandem()
tandem.hasBasket = true
tandem.currentNumberOfPassengers = 2
tandem.currentSpeed = 22.0
print("Tandem: (tandem.description)")
// Tandem: traveling at 22.0 miles per hour
## 重写 子类可以提供自定义的从超类继承来的实例方法、类型方法、实例属性、类型属性或下标,称为重写。
使用override关键字重写超类的特性,没有关键字的任何重写会导致编译错误。
访问超类方法、属性和下标
当子类重写方法、属性或下标时,可以将现有超类的实现用作重写的一部分,即在超类实现基础上重写。这时使用super前缀访问方法、属性或下标的超类版本:
-
名为someMethod()的重写方法可以通过在重写方法实现中调用super.someMetho()来调用someMethod()的超类版本。
-
被称为someProperty的被覆盖的属性可以在超级的getter或setter实现中以super.someProperty方式访问someProperty的超类版本。
-
someIndex的覆盖下标可以从覆盖的下标实现中访问与super [someIndex]相同的下标的超类版本。
方法重写
可以重写继承的实例或类型方法来提供子类中定制或替代方法的方法。
class Train: Vehicle {
override func makeNoise() {
print("Choo Choo")
}
}
let train = Train()
train.makeNoise()
// Prints "Choo Choo"
属性重写
可以重写继承的实例或类型属性,为该属性提供自定义getter和setter,或添加属性观察器以启用重写属性来观察底层属性值何时更改。
getter和setter属性重写
可以提供自定义的getter(和setter)来覆盖任何继承的属性,必须始终声明要覆盖的属性名和类型,以便编译器检查重写是否与具有同名同类型的超类属性匹配。
可以为超类的只读属性的重写同时提供getter和setter修改为读写属性,但不能将超类的读写属性重写为只读属性。
注意
当重写属性提供了setter时,还必须提供getter。若不想覆盖getter修改继承属性的值,可以从getter中返回super.someProperty以维持超类属性的getter实现。
以下为子类重写超类description属性并在超类实现基础上添加新功能:
class Car: Vehicle {
var gear = 1
override var description: String {
return super.description + " in gear (gear)"
}
}
let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print("Car: (car.description)")
// Car: traveling at 25.0 miles per hour in gear 3
属性观察器重写
重写属性会讲超类的属性观察器添加到继承的属性,不论该属性的实现方法如何都将能够在继承属性的值更改时收到通知。
注意
不能将属性观察器添加到继承的常量存储型属性或只读计算型属性,因为这些属性值不能更改。不能为同一属性同时提供重写的setter和重写的属性观察器,若要监听属性值的更改,并且已经提供重写的setter,则可以简单地监听重写的setter中任何值的更改。
class AutomaticCar: Car {
override var currentSpeed: Double {
didSet {
gear = Int(currentSpeed / 10.0) + 1
}
}
}
let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: (automatic.description)")
// AutomaticCar: traveling at 35.0 miles per hour in gear 4
## 防止重写 通过将方法、属性或下标标记为**final**防止被子类重写,如**final var**,**final func**,**final class fun**和**final subscript**。
任何试图在子类中重写标记为final的方法、属性或下标都将报告编译错误,也可以在扩展中使用final关键字。
可以在类定义中的class关键字之前添加final修饰符防止该类被子类化,任何试图子类化标记为final的类都将报告编译错误。