參考:http://wiki.jikexueyuan.com/project/swift/chapter2/13_Inheritance.htmlios
在Swift中,繼承是類和其餘類型區分開的基本行爲。swift
在 Swift 中,類能夠調用和訪問超類的方法,屬性和下標(subscripts),而且能夠重寫這些方法、屬性和下標腳原本優化或修改它們的行爲。Swift 會檢查你的重寫定義在超類中是否有匹配的定義,以此確保你的重寫行爲是正確的。markdown
能夠爲類中繼承來的屬性添加屬性觀察器,這樣一來,當屬性值改變時,類就會被通知到。能夠爲任何屬性添加屬性觀察器,不管它本來被定義爲存儲型屬性仍是計算型屬性。app
沒有繼承任何類的類,稱爲基類。ide
注意:Swift中任何類都沒有繼承一個通用的類(如Objective-C中的NSObject),因此定義類時只要沒有指定超類,該類就自動稱爲基類。優化
下面是一個基類Vehicle:ui
1 class Vehicle { 2 var currentSpeed = 0.0 3 var description: String { 4 return "traveling at \(currentSpeed) miles per hour" 5 } 6 func makeNoise() { 7 // do nothing - an arbitrary vehicle doesn't necessarily make a noise 8 } 9 }
能夠建立它的一個實例:spa
1 let someVehicle = Vehicle()
訪問它的description屬性:code
1 print("Vehicle: \(someVehicle.description)") 2 // Vehicle: traveling at 0.0 miles per hour
子類化,也就是在一個已存在的類的基礎上新建一個類。子類繼承父類(superclass)的特性,而後你能夠從新定義,也能夠定義新的特性。
1 class SomeSubclass: SomeSuperclass { 2 // subclass definition goes here 3 }
下面,新建Vehicle的子類:
1 class Bicycle: Vehicle { 2 var hasBasket = false 3 }
Bicycle自動得到Vehicle的全部特性,包括currentSpeed和description屬性、makeMoise()方法。
此外,Bicycle添加了一個新的默認值爲false的屬性hasBasket。
建立一個Bicycle的實例:
1 let bicycle = Bicycle() 2 bicycle.hasBasket = true
能夠修改它從父類繼承下來的屬性:
1 bicycle.currentSpeed = 15.0 2 print("Bicycle: \(bicycle.description)") 3 // Bicycle: traveling at 15.0 miles per hour
子類還能夠被子類化:
1 class Tandem: Bicycle { 2 var currentNumberOfPassengers = 0 3 }
建立一個Tandem的實例:
1 let tandem = Tandem() 2 tandem.hasBasket = true 3 tandem.currentNumberOfPassengers = 2 4 tandem.currentSpeed = 22.0 5 print("Tandem: \(tandem.description)") 6 // Tandem: traveling at 22.0 miles per hour
子類能夠提供實例方法、類型方法、實例屬性、類型屬性、下標的自定義實現,不然,將從超類繼承。這就是重寫的概念。
若是要重寫某個特性,你須要在重寫定義的前面加上override
關鍵字。
這麼作,你就代表了你是想提供一個重寫版本,而非錯誤地提供了一個相同的定義。意外的重寫行爲可能會致使不可預知的錯誤,任何缺乏override
關鍵字的重寫都會在編譯時被診斷爲錯誤。
override
關鍵字會提醒 Swift 編譯器去檢查該類的超類(或其中一個父類)是否有匹配重寫版本的聲明。這個檢查能夠確保你的重寫定義是正確的。
當你在子類中重寫父類的方法,屬性或下標腳本時,有時在你的重寫版本中使用已經存在的父類實現會大有裨益。好比,你能夠優化已有實現的行爲,或在一個繼承來的變量中存儲一個修改過的值。
在合適的地方,你能夠經過使用super
前綴來訪問父類版本的方法,屬性或下標腳本:
someMethod
的重寫實現中,能夠經過super.someMethod()
來調用超類版本的someMethod
方法。someProperty
的 getter 或 setter 的重寫實現中,能夠經過super.someProperty
來訪問超類版本的someProperty
屬性。super[someIndex]
來訪問超類版本中的相同下標腳本。在子類中,你能夠重寫繼承來的實例方法或類方法,提供一個定製或替代的方法實現。
1 class Train: Vehicle { 2 override func makeNoise() { 3 print("Choo Choo") 4 } 5 }
調用重寫的方法:
1 let train = Train() 2 train.makeNoise() 3 // prints "Choo Choo"
你能夠重寫繼承來的實例屬性或類屬性,提供本身定製的getter和setter,或者添加屬性觀察器來觀察屬性值何時發生改變。
你能夠提供定製的 getter(或 setter)來重寫任意繼承來的屬性,不管繼承來的屬性是存儲型的仍是計算型的屬性。子類並不知道繼承來的屬性是存儲型的仍是計算型的,它只知道繼承來的屬性會有一個名字和類型。你在重寫一個屬性時,必需將它的名字和類型都寫出來。這樣才能使編譯器去檢查你重寫的屬性是與超類中同名同類型的屬性相匹配的。
你能夠將一個繼承來的只讀屬性重寫爲一個讀寫屬性,只須要你在重寫版本的屬性裏提供 getter 和 setter 便可。可是,你不能夠將一個繼承來的讀寫屬性重寫爲一個只讀屬性。
注意:若是你在重寫屬性中提供了 setter,那麼你也必定要提供 getter。若是你不想在重寫版本中的 getter 裏修改繼承來的屬性值,你能夠直接經過super.someProperty
來返回繼承來的值,其中someProperty
是你要重寫的屬性的名字。
class Car: Vehicle { var gear = 1 override var description: String { return super.description + " in gear \(gear)" } }
description
屬性的override從調用super.description開始,在父類的基礎上增長了一些描述。
1 let car = Car() 2 car.currentSpeed = 25.0 3 car.gear = 3 4 print("Car: \(car.description)") 5 // Car: traveling at 25.0 miles per hour in gear 3
注意:不能給繼承的常量存儲屬性和只讀計算型屬性添加屬性觀察器,這些屬性的值不能設置,因此也沒法添加相應的willSet和didSet方法。另外,對於同一個屬性,不能同時重寫setter和重寫屬性觀察器,若是已經爲一個屬性提供了自定義的setter,那麼只能在這個setter中觀察屬性的變化。
1 class AutomaticCar: Car { 2 override var currentSpeed: Double { 3 didSet { 4 gear = Int(currentSpeed / 10.0) + 15 } 5 } 6 }
只要設置currentSpeed屬性,didSet就會設置相應的gear。
1 let automatic = AutomaticCar() 2 automatic.currentSpeed = 35.0 3 print("AutomaticCar: \(automatic.description)") 4 // AutomaticCar: traveling at 35.0 miles per hour in gear 4 5
你能夠經過把方法,屬性或下標腳本標記爲final
來防止它們被重寫,只須要在聲明關鍵字前加上final
特性便可。(例如:final var
, final func
, final class func
, 以及 final subscript
)
若是你重寫了final
方法,屬性或下標,在編譯時會報錯。在類擴展中的方法,屬性或下標腳本也能夠在擴展的定義裏標記爲 final。
你能夠經過在關鍵字class
前添加final
特性(final class
)來將整個類標記爲 final 的,這樣的類是不可被繼承的,任何子類試圖繼承此類時,在編譯時會報錯。