发布于 2015-06-14 01:46:21 | 305 次阅读 | 评论: 0 | 来源: 网络整理
子类可以为继承来的实例方法(instance method),类方法(class method),实例属性(instance property),或下标脚本(subscript)提供自己定制的实现(implementation)。我们把这种行为叫重写(overriding)。
如果要重写某个特性,你需要在重写定义的前面加上override
关键字。这么做,你就表明了你是想提供一个重写版本,而非错误地提供了一个相同的定义。意外的重写行为可能会导致不可预知的错误,任何缺少override
关键字的重写都会在编译时被诊断为错误。
override
关键字会提醒 Swift 编译器去检查该类的超类(或其中一个父类)是否有匹配重写版本的声明。这个检查可以确保你的重写定义是正确的。
当你在子类中重写超类的方法,属性或下标脚本时,有时在你的重写版本中使用已经存在的超类实现会大有裨益。比如,你可以优化已有实现的行为,或在一个继承来的变量中存储一个修改过的值。
在合适的地方,你可以通过使用super
前缀来访问超类版本的方法,属性或下标脚本:
someMethod
的重写实现中,可以通过super.someMethod()
来调用超类版本的someMethod
方法。someProperty
的 getter 或 setter 的重写实现中,可以通过super.someProperty
来访问超类版本的someProperty
属性。super[someIndex]
来访问超类版本中的相同下标脚本。在子类中,你可以重写继承来的实例方法或类方法,提供一个定制或替代的方法实现。
下面的例子定义了Vehicle
的一个新的子类,叫Car
,它重写了从Vehicle
类继承来的description
方法:
class Car: Vehicle {
var speed: Double = 0.0
init() {
super.init()
maxPassengers = 5
numberOfWheels = 4
}
override func description() -> String {
return super.description() + "; "
+ "traveling at (speed) mph"
}
}
Car
声明了一个新的存储型属性speed
,它是Double
类型的,默认值是0.0
,表示“时速是0英里”。Car
有自己的初始化器,它将乘客的最大数量设为5,轮子数量设为4。
Car
重写了继承来的description
方法,它的声明与Vehicle
中的description
方法一致,声明前面加上了override
关键字。
Car
中的description
方法并非完全自定义,而是通过super.description
使用了超类Vehicle
中的description
方法,然后再追加一些额外的信息,比如汽车的当前速度。
如果你创建一个Car
的新实例,并打印description
方法的输出,你就会发现描述信息已经发生了改变:
let car = Car()
println("Car: (car.description())")
// Car: 4 wheels; up to 5 passengers; traveling at 0.0 mph
你可以重写继承来的实例属性或类属性,提供自己定制的getter和setter,或添加属性观察器使重写的属性观察属性值什么时候发生改变。
你 可以提供定制的 getter(或 setter)来重写任意继承来的属性,无论继承来的属性是存储型的还是计算型的属性。子类并不知道继承来的属性是存储型的还是计算型的,它只知道继承来 的属性会有一个名字和类型。你在重写一个属性时,必需将它的名字和类型都写出来。这样才能使编译器去检查你重写的属性是与超类中同名同类型的属性相匹配 的。
你可以将一个继承来的只读属性重写为一个读写属性,只需要你在重写版本的属性里提供 getter 和 setter 即可。但是,你不可以将一个继承来的读写属性重写为一个只读属性。
注意:
如果你在重写属性中提供了 setter,那么你也一定要提供 getter。如果你不想在重写版本中的 getter 里修改继承来的属性值,你可以直接返回super.someProperty
来返回继承来的值。正如下面的SpeedLimitedCar
的例子所示。
以下的例子定义了一个新类,叫SpeedLimitedCar
,它是Car
的子类。类SpeedLimitedCar
表示安装了限速装置的车,它的最高速度只能达到40mph。你可以通过重写继承来的speed
属性来实现这个速度限制:
class SpeedLimitedCar: Car {
override var speed: Double {
get {
return super.speed
}
set {
super.speed = min(newValue, 40.0)
}
}
}
当你设置一个SpeedLimitedCar
实例的speed
属性时,属性setter的实现会去检查新值与限制值40mph的大小,它会将超类的speed
设置为newValue
和40.0
中较小的那个。这两个值哪个较小由min
函数决定,它是Swift标准库中的一个全局函数。min
函数接收两个或更多的数,返回其中最小的那个。
如果你尝试将SpeedLimitedCar
实例的speed
属性设置为一个大于40mph的数,然后打印description
函数的输出,你会发现速度被限制在40mph:
let limitedCar = SpeedLimitedCar()
limitedCar.speed = 60.0
println("SpeedLimitedCar: (limitedCar.description())")
// SpeedLimitedCar: 4 wheels; up to 5 passengers; traveling at 40.0 mph
你可以在属性重写中为一个继承来的属性添加属性观察器。这样一来,当继承来的属性值发生改变时,你就会被通知到,无论那个属性原本是如何实现的。关于属性观察器的更多内容,请看属性观察器。
注意:
你不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器。这些属性的值是不可以被设置的,所以,为它们提供willSet
或didSet
实现是不恰当。此外还要注意,你不可以同时提供重写的 setter 和重写的属性观察器。如果你想观察属性值的变化,并且你已经为那个属性提供了定制的 setter,那么你在 setter 中就可以观察到任何值变化了。
下面的例子定义了一个新类叫AutomaticCar
,它是Car
的子类。AutomaticCar
表示自动挡汽车,它可以根据当前的速度自动选择合适的挡位。AutomaticCar
也提供了定制的description
方法,可以输出当前挡位。
class AutomaticCar: Car {
var gear = 1
override var speed: Double {
didSet {
gear = Int(speed / 10.0) + 1
}
}
override func description() -> String {
return super.description() + " in gear (gear)"
}
}
当你设置AutomaticCar
的speed
属性,属性的didSet
观察器就会自动地设置gear
属性,为新的速度选择一个合适的挡位。具体来说就是,属性观察器将新的速度值除以10,然后向下取得最接近的整数值,最后加1来得到档位gear
的值。例如,速度为10.0时,挡位为1;速度为35.0时,挡位为4:
let automatic = AutomaticCar()
automatic.speed = 35.0
println("AutomaticCar: (automatic.description())")
// AutomaticCar: 4 wheels; up to 5 passengers; traveling at 35.0 mph in gear 4