Swift 5.x - 繼承(中文文檔)

引言

繼續(xù)學(xué)習(xí)Swift文檔驱犹,從上一章節(jié):下標(biāo)雄驹,我們學(xué)習(xí)了Swift下標(biāo)相關(guān)的內(nèi)容医舆,如下標(biāo)語法象缀、下標(biāo)用法爷速、下標(biāo)選項和類型下標(biāo)等這些內(nèi)容⊙胄牵現(xiàn)在,我們學(xué)習(xí)Swift的繼承相關(guān)的內(nèi)容遍希。由于篇幅較長等曼,這里分篇來記錄里烦,接下來凿蒜,F(xiàn)ighting!

熟悉這一章節(jié)的朋友可以直接跳過下一章節(jié):初始化

繼承

一個類可以從另一個類繼承方法胁黑,屬性和其他特征废封。 當(dāng)一個類從另一個類繼承時丧蘸,繼承的類稱為子類漂洋,而其繼承的類稱為其父類。 繼承是一種基本行為力喷,可將Swift中的類與其他類型區(qū)分開刽漂。

Swift中的類可以調(diào)用和訪問屬于其父類的方法,屬性和下標(biāo)弟孟,并可以提供這些方法贝咙,重寫屬性和下標(biāo)以完善或修改其行為。 Swift通過檢查覆蓋定義是否具有匹配的父類定義來幫助確保覆蓋是正確的拂募。

類還可以將屬性觀察器添加到繼承的屬性中庭猩,以便在屬性值更改時得到通知。 可以將屬性觀察器添加到任何屬性陈症,而不管其最初是定義為存儲屬性還是計算屬性蔼水。

1 定義基類

任何不從另一個類繼承的類都稱為基類。

注意
Swift類不能從通用基類繼承录肯。 您沒有指定父類而定義的類將自動成為基類供您構(gòu)建趴腋。

下面的示例定義了一個稱為Vehicle的基類。 該基類定義了一個稱為currentSpeed的存儲屬性论咏,默認(rèn)值為0.0(推斷屬性類型為Double)于样。 currentSpeed屬性的值由一個稱為description的只讀計算出的String屬性用于創(chuàng)建車輛的描述。

Vehicle基類還定義了一個稱為makeNoise的方法潘靖。 此方法實際上不對基礎(chǔ)Vehicle實例執(zhí)行任何操作穿剖,但稍后將由Vehicle的子類自定義:

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
    }
}

使用初始化器語法創(chuàng)建一個Vehicle的新實例,該實例被寫為類型名稱卦溢,后跟空括號:

let someVehicle = Vehicle()

創(chuàng)建新的Vehicle實例后糊余,您可以訪問其description屬性秀又,以打印出人類可以理解的車輛當(dāng)前速度的描述:

print("Vehicle: \(someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour

Vehicle類定義了任意車輛的共同特征,但其本身并沒有太多用途贬芥。 為了使其更有用吐辙,您需要對其進(jìn)行改進(jìn)以描述更多特定類型的車輛。

2 子類

子類化是在現(xiàn)有類的基礎(chǔ)上建立新類的行為蘸劈。 子類繼承現(xiàn)有類的特征昏苏,然后可以對其進(jìn)行優(yōu)化。 您還可以向子類添加新特征威沫。

要表明子類具有父類贤惯,請在父類名稱之前寫上子類名稱,并用冒號分隔:

class SomeSubclass: SomeSuperclass {
    // subclass definition goes here
}

下面的示例定義了一個名為Bicycle的子類棒掠,并帶有Vehicle的父類:

class Bicycle: Vehicle {
    var hasBasket = false
}

新的Bicycle類自動獲得了Vehicle的所有特征孵构,例如currentSpeed和description屬性以及makeNoise()方法。

除其繼承的特征外烟很,Bicycle類還定義了一個新的存儲屬性hasBasket颈墅,其默認(rèn)值為false(為該屬性推斷為Bool類型)。

默認(rèn)情況下雾袱,您創(chuàng)建的任何新Bicycle實例都沒有籃子恤筛。 創(chuàng)建特定的Bicycle實例后,可以將hasBasket屬性設(shè)置為true:

let bicycle = Bicycle()
bicycle.hasBasket = true

您還可以修改Bicycle實例的繼承的currentSpeed屬性芹橡,并查詢該實例的繼承的description屬性:

bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour

子類本身可以被子類化毒坛。 下一個示例為稱為“雙人”的兩人座自行車創(chuàng)建Bicycle的子類:

class Tandem: Bicycle {
    var currentNumberOfPassengers = 0
}

Tandem繼承了Bicycle的所有屬性和方法,而后者又繼承了Vehicle的所有屬性和方法僻族。 Tandem子類還添加了一個名為currentNumberOfPassengers的新存儲屬性粘驰,默認(rèn)值為0。

如果創(chuàng)建Tandem實例述么,則可以使用它的任何新屬性和繼承的屬性蝌数,并查詢它從Vehicle繼承的只讀description屬性:

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

3 重寫

子類可以提供其自己的實例方法,類型方法度秘,實例屬性顶伞,類型屬性或下標(biāo)的自定義實現(xiàn),否則該實例方法將從超類繼承剑梳。 這稱為重寫唆貌。

要重寫原本會被繼承的特征,請在您的重寫定義前添加override關(guān)鍵字垢乙。 這樣做可以明確您打算提供替代锨咙,并且沒有錯誤地提供匹配的定義。 偶然的重寫可能會導(dǎo)致意外的行為追逮,并且在編譯代碼時酪刀,任何不帶有override關(guān)鍵字的替代都會被診斷為錯誤粹舵。

Override關(guān)鍵字還會提示Swift編譯器檢查您的重寫類的父類(或其父類之一)是否具有與您為該替代提供的聲明相匹配的聲明。 此檢查可確保您的重寫定義正確骂倘。

3.1 訪問子類的方法眼滤、屬性和下標(biāo)

當(dāng)為子類提供方法,屬性或下標(biāo)替代時历涝,將現(xiàn)有的超類實現(xiàn)用作替代的一部分有時會很有用诅需。 例如,您可以優(yōu)化該現(xiàn)有實現(xiàn)的行為荧库,或者將修改后的值存儲在現(xiàn)有的繼承變量中堰塌。

在適當(dāng)?shù)那闆r下,您可以使用super前綴訪問方法电爹,屬性或下標(biāo)的超類版本:

  • 名稱為someMethod()的重寫方法可以通過在重寫方法實現(xiàn)中調(diào)用super.someMethod()來調(diào)用someMethod()的父類方法蔫仙。
  • 重寫的名稱為someProperty的屬性可以在重寫的getter或setter實現(xiàn)中以super.someProperty的方式訪問someProperty的父類屬性料睛。
  • someIndex的重寫下標(biāo)可以從重寫下標(biāo)實現(xiàn)中訪問與super [someIndex]相同的下標(biāo)的父類下標(biāo)丐箩。

3.2 重寫方法

您可以重寫繼承的實例或類型方法,以在子類中提供該方法的定制或替代實現(xiàn)恤煞。

以下示例定義了一個名為Train的Vehicle的新子類屎勘,該子類重寫Train從Vehicle繼承的makeNoise()方法:

class Train: Vehicle {
    override func makeNoise() {
        print("Choo Choo")
    }
}

如果創(chuàng)建一個Train的新實例并調(diào)用其makeNoise()方法,則可以看到該方法的Train子類版本稱為:

let train = Train()
train.makeNoise()
// Prints "Choo Choo"

3.3 重寫屬性

您可以重寫繼承的實例或類型屬性居扒,以為該屬性提供自己的自定義getter和setter概漱,或添加屬性觀察器以使重寫的屬性能夠在基礎(chǔ)屬性值更改時進(jìn)行觀察。

重寫屬性的Getters和Setters
您可以提供一個自定義getter(如果合適的話喜喂,可以使用setter)來重寫任何繼承的屬性瓤摧,而不管該繼承的屬性是在源上實現(xiàn)為存儲屬性還是計算屬性。 子類不知道繼承屬性的存儲或計算性質(zhì)玉吁,它僅知道繼承屬性具有特定名稱和類型照弥。 您必須始終聲明要重寫的屬性的名稱和類型,以使編譯器能夠檢查您的重寫是否與具有相同名稱和類型的父類屬性匹配进副。

通過在子類屬性重寫中同時提供getter和setter这揣,可以將繼承的只讀屬性呈現(xiàn)為讀寫屬性。 但是影斑,您不能將繼承的讀寫屬性表示為只讀屬性给赞。

注意
如果在屬性替代中提供了一個setter,則還必須為該替代提供一個getter矫户。 如果您不想在重寫的getter中修改繼承的屬性的值片迅,則可以通過從getter返回super.someProperty來傳遞繼承的值,其中someProperty是您要重寫的屬性的名稱皆辽。

以下示例定義了一個名為Car的新類柑蛇,它是Vehicle的子類罐旗。 Car類引入了一個稱為gear的新存儲屬性,其默認(rèn)整數(shù)值為1唯蝶。Car類還覆蓋了它從Vehicle繼承的description屬性九秀,以提供包括當(dāng)前gear的自定義描述:

class Car: Vehicle {
    var gear = 1
    override var description: String {
        return super.description + " in gear \(gear)"
    }
}

對description屬性的重寫是通過調(diào)用super.description開始的,super.description返回Vehicle類的description屬性粘我。 然后鼓蜒,汽車類的描述版本會在此描述的末尾添加一些額外的文字,以提供有關(guān)當(dāng)前裝備的信息征字。

如果創(chuàng)建Car類的實例并設(shè)置其gear和currentSpeed屬性都弹,則可以看到其description屬性返回在Car類中定義的定制描述:

let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print("Car: \(car.description)")
// Car: traveling at 25.0 miles per hour in gear 3

重寫屬性監(jiān)聽
您可以使用屬性重寫將屬性觀察器添加到繼承的屬性。 這使您可以在繼承屬性的值更改時得到通知匙姜,而無論該屬性最初是如何實現(xiàn)的畅厢。 有關(guān)屬性觀察器的更多信息,請參見Property Observers氮昧。

注意
您不能將屬性觀察器添加到繼承的常量存儲屬性或繼承的只讀計算屬性框杜。 這些屬性的值無法設(shè)置,因此不建議將willSet或didSet實現(xiàn)作為覆蓋的一部分提供袖肥。

還要注意咪辱,您不能為同一屬性同時提供覆蓋設(shè)置器和覆蓋屬性觀察器。 如果您想觀察屬性值的變化椎组,并且已經(jīng)在為該屬性提供自定義設(shè)置器油狂,則可以簡單地觀察自定義設(shè)置器中的任何值更改。

下面的示例定義一個名為AutomaticCar的新類寸癌,它是Car的子類专筷。 AutomaticCar類代表具有自動變速箱的汽車,該變速箱會根據(jù)當(dāng)前速度自動選擇要使用的檔位:

class AutomaticCar: Car {
    override var currentSpeed: Double {
        didSet {
            gear = Int(currentSpeed / 10.0) + 1
        }
    }
}

每當(dāng)您設(shè)置AutomaticCar實例的currentSpeed屬性時蒸苇,該屬性的didSet觀察器都會將該實例的gear屬性設(shè)置為新速度的適當(dāng)齒輪磷蛹。 具體來說,屬性觀察者選擇的齒輪是新的currentSpeed值除以10填渠,四舍五入到最接近的整數(shù)加1弦聂。35.0的速度產(chǎn)生4的齒輪:

let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")
// AutomaticCar: traveling at 35.0 miles per hour in gear 4

4 防止重寫

您可以通過將方法,屬性或下標(biāo)標(biāo)記為final來防止其被重寫氛什。 為此莺葫,可以在方法,屬性或下標(biāo)的Introductionr關(guān)鍵字(例如final var枪眉,final func捺檬,final class func和final下標(biāo))之前編寫final修飾符。

嘗試重寫子類中的最終方法贸铜,屬性或下標(biāo)的任何嘗試都將報告為編譯時錯誤堡纬。 您在擴(kuò)展程序的類中添加的方法聂受,屬性或下標(biāo)也可以在擴(kuò)展程序的定義中標(biāo)記為final。

您可以通過在類定義中的class關(guān)鍵字之前編寫final修飾符烤镐,將整個類標(biāo)記為(final class)蛋济。 任何嘗試將最終類作為子類的嘗試都將報告為編譯時錯誤。

總結(jié)

這一章節(jié)主要講的是:

  • 繼承的作用:可以繼承父類定義的屬性炮叶、方法和下標(biāo)碗旅,以擴(kuò)展自定義的功能。
  • 沒有從父類繼承的類都是基類镜悉,在基類里面定義一些基本的屬性和方法祟辟,以提供子類來擴(kuò)展。
  • 使用override關(guān)鍵詞修飾父類的屬性或方法來重寫父類里面實現(xiàn)的功能侣肄《希可以重寫屬性的Getters和Setters担猛、屬性監(jiān)聽留量。
  • 使用final關(guān)鍵詞修飾可以防止重寫雄人。

好了,有收獲的朋友麻煩給個鼓勵哦缰贝,謝謝啦~

上一章節(jié):下標(biāo)

下一章節(jié):初始化

參考文檔: Swift - Inheritance

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末馍悟,一起剝皮案震驚了整個濱河市畔濒,隨后出現(xiàn)的幾起案子剩晴,更是在濱河造成了極大的恐慌,老刑警劉巖侵状,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赞弥,死亡現(xiàn)場離奇詭異,居然都是意外死亡趣兄,警方通過查閱死者的電腦和手機(jī)绽左,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來艇潭,“玉大人拼窥,你說我怎么就攤上這事√D” “怎么了鲁纠?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鳍寂。 經(jīng)常有香客問我改含,道長,這世上最難降的妖魔是什么迄汛? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任捍壤,我火速辦了婚禮骤视,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鹃觉。我一直安慰自己专酗,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布盗扇。 她就那樣靜靜地躺著笼裳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪粱玲。 梳的紋絲不亂的頭發(fā)上躬柬,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機(jī)與錄音抽减,去河邊找鬼允青。 笑死,一個胖子當(dāng)著我的面吹牛卵沉,可吹牛的內(nèi)容都是我干的颠锉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼史汗,長吁一口氣:“原來是場噩夢啊……” “哼琼掠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起停撞,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤瓷蛙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后戈毒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艰猬,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年埋市,在試婚紗的時候發(fā)現(xiàn)自己被綠了冠桃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡道宅,死狀恐怖食听,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情污茵,我是刑警寧澤樱报,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站省咨,受9級特大地震影響肃弟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一笤受、第九天 我趴在偏房一處隱蔽的房頂上張望穷缤。 院中可真熱鬧,春花似錦箩兽、人聲如沸津肛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽身坐。三九已至,卻和暖如春落包,著一層夾襖步出監(jiān)牢的瞬間部蛇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工咐蝇, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留涯鲁,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓有序,卻偏偏與公主長得像抹腿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子旭寿,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 引言 繼續(xù)學(xué)習(xí)Swift文檔警绩,從上一章節(jié):繼承,我們學(xué)習(xí)了Swift繼承相關(guān)的內(nèi)容盅称,如繼承的作用肩祥、重寫父類的方法和...
    shiyueZ閱讀 2,081評論 0 2
  • 引言 今天,開始系統(tǒng)學(xué)習(xí)Swift微渠,以前都是零零散散的看看的let和var的區(qū)別搭幻、泛型,只知道它是一個面向協(xié)議且類...
    shiyueZ閱讀 3,651評論 0 11
  • 繼承 類可以繼承另一個類的方法逞盆、屬性以及其他某些特征。當(dāng) A 類繼承 B 類時松申,A 類為子類云芦,B 類為父類。在 S...
    三個像素閱讀 1,555評論 0 1
  • 引言 繼續(xù)學(xué)習(xí)Swift文檔贸桶,從上一章節(jié):初始化舅逸,我們學(xué)習(xí)了Swift初始化相關(guān)的內(nèi)容,如類皇筛、結(jié)構(gòu)體和枚舉初始化方...
    shiyueZ閱讀 532評論 0 1
  • 引言 繼續(xù)學(xué)習(xí)Swift文檔琉历,從上一章節(jié):析構(gòu)函數(shù),我們學(xué)習(xí)了Swift析構(gòu)函數(shù)相關(guān)的內(nèi)容。現(xiàn)在旗笔,我們學(xué)習(xí)Swif...
    shiyueZ閱讀 644評論 0 0