子類可以為繼承來的實例方法(instance method),類方法(class method),實例屬性(instance property),或下標腳本(subscript)提供自己定制的實現(xiàn)(implementation)。我們把這種行為叫重寫(overriding)。
如果要重寫某個特性,你需要在重寫定義的前面加上override關鍵字。這么做,你就表明了你是想提供一個重寫版本,而非錯誤地提供了一個相同的定義。意外的重寫行為可能會導致不可預知的錯誤,任何缺少override關鍵字的重寫都會在編譯時被診斷為錯誤。
override關鍵字會提醒 Swift 編譯器去檢查該類的超類(或其中一個父類)是否有匹配重寫版本的聲明。這個檢查可以確保你的重寫定義是正確的。
當你在子類中重寫超類的方法,屬性或下標腳本時,有時在你的重寫版本中使用已經(jīng)存在的超類實現(xiàn)會大有裨益。比如,你可以優(yōu)化已有實現(xiàn)的行為,或在一個繼承來的變量中存儲一個修改過的值。
在合適的地方,你可以通過使用super前綴來訪問超類版本的方法,屬性或下標腳本:
someMethod的重寫實現(xiàn)中,可以通過super.someMethod()來調(diào)用超類版本的someMethod方法。someProperty的 getter 或 setter 的重寫實現(xiàn)中,可以通過super.someProperty來訪問超類版本的someProperty屬性。super[someIndex]來訪問超類版本中的相同下標腳本。在子類中,你可以重寫繼承來的實例方法或類方法,提供一個定制或替代的方法實現(xiàn)。
下面的例子定義了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有自己的初始化器,它將乘客的最大數(shù)量設為5,輪子數(shù)量設為4。
Car重寫了繼承來的description方法,它的聲明與Vehicle中的description方法一致,聲明前面加上了override關鍵字。
Car中的description方法并非完全自定義,而是通過super.description使用了超類Vehicle中的description方法,然后再追加一些額外的信息,比如汽車的當前速度。
如果你創(chuàng)建一個Car的新實例,并打印description方法的輸出,你就會發(fā)現(xiàn)描述信息已經(jīng)發(fā)生了改變:
let car = Car()
println("Car: \(car.description())")
// Car: 4 wheels; up to 5 passengers; traveling at 0.0 mph
你可以重寫繼承來的實例屬性或類屬性,提供自己定制的getter和setter,或添加屬性觀察器使重寫的屬性觀察屬性值什么時候發(fā)生改變。
你可以提供定制的 getter(或 setter)來重寫任意繼承來的屬性,無論繼承來的屬性是存儲型的還是計算型的屬性。子類并不知道繼承來的屬性是存儲型的還是計算型的,它只知道繼承來的屬性會有一個名字和類型。你在重寫一個屬性時,必需將它的名字和類型都寫出來。這樣才能使編譯器去檢查你重寫的屬性是與超類中同名同類型的屬性相匹配的。
你可以將一個繼承來的只讀屬性重寫為一個讀寫屬性,只需要你在重寫版本的屬性里提供 getter 和 setter 即可。但是,你不可以將一個繼承來的讀寫屬性重寫為一個只讀屬性。
注意:
如果你在重寫屬性中提供了 setter,那么你也一定要提供 getter。如果你不想在重寫版本中的 getter 里修改繼承來的屬性值,你可以直接返回super.someProperty來返回繼承來的值。正如下面的SpeedLimitedCar的例子所示。
以下的例子定義了一個新類,叫SpeedLimitedCar,它是Car的子類。類SpeedLimitedCar表示安裝了限速裝置的車,它的最高速度只能達到40mph。你可以通過重寫繼承來的speed屬性來實現(xiàn)這個速度限制:
<