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