繼承 (Inheritance)
自從蘋(píng)果2014年發(fā)布Swift,到現(xiàn)在已經(jīng)兩年多了掉伏,而Swift也來(lái)到了3.1版本。去年利用工作之余,共花了兩個(gè)多月的時(shí)間把官方的Swift編程指南看完∑偷耍現(xiàn)在整理一下筆記,回顧一下以前的知識(shí)伴鳖。有需要的同學(xué)可以去看官方文檔>>节值。
定義基類 (Defining a Base Class)
沒(méi)有繼承其他類的類,叫做基類榜聂。
注意:Swift的類不用繼承一個(gè)通用的基類搞疗。
下面是定義一個(gè)Vehicle
基類,定義了任意機(jī)動(dòng)車的共同特征:
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()
print("Vehicle: \(someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour
子類化 (Subclassing)
子類繼承了父類的特征须肆,子類也可以添加新的特征匿乃。
繼承的通用形式:
class SomeSubclass: SomeSuperclass {
// subclass definition goes here
}
下面是定義了一個(gè)Vehicle
的子類Bicycle
:
class Bicycle: Vehicle {
var hasBasket = false
}
Bycycle
自動(dòng)獲得了Vehicle
的currentSpeed
和description
屬性,還有makeNoise()
方法豌汇。另外還添加了一個(gè)存儲(chǔ)屬性hasBasket
,默認(rèn)值為false
(被推斷為Bool類型)幢炸。
默認(rèn)情況下自行車是沒(méi)有籃子的,創(chuàng)建一個(gè)自行車實(shí)例后拒贱,把hasBasket
設(shè)置為true
:
let bicycle = Bicycle()
bicycle.hasBasket = true
還可以修改通過(guò)繼承得到的屬性:
bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour
子類又可以被子類化宛徊。下面創(chuàng)建了一個(gè)Bicycle
的子類兩輪自行車Tandem
:
class Tandem: Bicycle {
var currentNumberOfPassangers = 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
Tandem
繼承了Bicycle
的所有屬性和方法,并依次繼承了Vehicle
的所有屬性和方法逻澳,還另外添加了一個(gè)屬性currentNumberOfPassengers
岩调,默認(rèn)為0。
重寫(xiě) (Overriding)
子類可以自定義從父類繼承的實(shí)例方法赡盘、類方法号枕、實(shí)例屬性、類屬性或者下標(biāo)的實(shí)現(xiàn)陨享,稱為重寫(xiě)葱淳。使用override
關(guān)鍵字進(jìn)行重寫(xiě)钝腺。
訪問(wèn)父類的方法、屬性和下標(biāo) (Accessing Superclass Method, Properties and Subscripts)
當(dāng)重寫(xiě)父類的方法赞厕、屬性或者下標(biāo)時(shí)艳狐,把已經(jīng)存在的父類實(shí)現(xiàn)作為重寫(xiě)的一部分是非常有用的。
使用super
來(lái)訪問(wèn)父類的方法皿桑、屬性或者下標(biāo)的實(shí)現(xiàn):
- 子類的
someMethod()
方法可以通過(guò)super.someMethod()
來(lái)訪問(wèn)父類的somemMethod()
實(shí)現(xiàn)毫目。 - 子類的
someProperty
屬性可以通過(guò)super.someProperty
來(lái)訪問(wèn)父類的someProperty
屬性。 - 子類的
someIndex
下標(biāo)可以通過(guò)super[someIndex]
來(lái)訪問(wèn)父類的同一個(gè)下標(biāo)實(shí)現(xiàn)诲侮。
重寫(xiě)方法 (Overriding Methods)
創(chuàng)建Vehicle
的一個(gè)子類Train
镀虐,并重寫(xiě)makeNoise()
方法:
class Train: Vehicle {
override func makeNoise() {
print("Choo Choo")
}
}
創(chuàng)建一個(gè)Train
實(shí)例,并調(diào)用makeNoise()
方法沟绪,實(shí)際調(diào)用的是子類的版本:
let train = Train()
train.makeNoise()
// Prints "Choo Choo"
重寫(xiě)屬性 (Overriding Properties)
我們可以重寫(xiě)通過(guò)繼承得到的實(shí)例屬性和類屬性刮便,或者添加屬性觀察者來(lái)監(jiān)測(cè)屬性值的變化。
重寫(xiě)屬性的getter和setter方法 (Overriding Property Getters and Setters)
子類是不知道通過(guò)繼承得到的存儲(chǔ)屬性和計(jì)算屬性的本質(zhì)绽慈,他只知道這些屬性的名字和類型恨旱。
我們可以把繼承得到的只讀屬性重寫(xiě)為可讀可寫(xiě)屬性,但是不能把繼承得到的可讀可寫(xiě)屬性重寫(xiě)范圍只讀屬性坝疼。
注意:如果在重寫(xiě)屬性時(shí)搜贤,提供了setter方法,我們必須也提供一個(gè)getter方法钝凶。在重寫(xiě)getter方法時(shí)仪芒,如果不想改變繼承得到的屬性值,我們可以在getter方法中返回super.someProperty
腿椎,someProperty
是正在重寫(xiě)的屬性名字桌硫。
class Car: Vehicle {
var gear = 1
override var description: String {
return super.description + " in gear \(gear)"
}
}
重寫(xiě)屬性觀察者 (Overriding Property Observers)
我們可以使用屬性重寫(xiě)來(lái)把屬性觀察者添加到繼承得到的屬性中。當(dāng)繼承得到的屬性值發(fā)生改變時(shí)啃炸,我們可以做出響應(yīng)铆隘。
注意:不能把屬性觀察者添加到繼承得到的常量存儲(chǔ)屬性或者只讀計(jì)算屬性。因?yàn)檫@些屬性不能被設(shè)置新的值南用,所有不能使用willSet
和didSet
觀察者膀钠。另外,也不能在重寫(xiě)屬性時(shí)同時(shí)重寫(xiě)setter方法和屬性觀察者裹虫。如果要監(jiān)測(cè)屬性值的變化肿嘲,可以在自定義的setter方法監(jiān)測(cè)。
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
當(dāng)設(shè)置currentSpeed
屬性時(shí)筑公,didSet
觀察者內(nèi)部給gear
設(shè)置了一個(gè)新的值雳窟。
防止重寫(xiě) (Preventing Overrides)
我們可以在定義方法、屬性或者下標(biāo)時(shí)匣屡,在最前面加上final
關(guān)鍵字來(lái)阻止子類重寫(xiě)(例如final var
封救、final func
拇涤、final class func
、final subscript
)誉结。
如果嘗試修改final
標(biāo)記的方法鹅士、屬性或者下標(biāo),會(huì)報(bào)編譯錯(cuò)誤惩坑。在擴(kuò)展(Extension)中定義的方法掉盅、屬性或者下標(biāo)都可以使用final
。
在定義類時(shí)以舒,在class
前面加上final
來(lái)阻止這個(gè)類被繼承趾痘。
第十三部分完。下個(gè)部分:【Swift 3.1】14 - 初始化 (Initialization)
如果有錯(cuò)誤的地方稀轨,歡迎指正扼脐!謝謝岸军!