繼承
定義一個基類 :不繼承于其它類的類,稱之為基類。
重寫:如果要重寫某個特性当船,你需要在重寫定義的前面加上?override?關(guān)鍵字
override?關(guān)鍵字會提醒 Swift 編譯器去檢查該類的超類(或其中一個父類)是否有匹配重寫版本的聲明沦零。這個檢查可以確保你的重寫定義是正確的。
你不可以為繼承來的常量存儲型屬性或繼承來的只讀計(jì)算型屬性添加屬性觀察器篮灼。這些屬性的值是不可以被設(shè)置的忘古,所以,為它們提供?willSet?或?didSet?實(shí)現(xiàn)也是不恰當(dāng)诅诱。 此外還要注意髓堪,你不可以同時提供重寫的 setter 和重寫的屬性觀察器。如果你想觀察屬性值的變化逢艘,并且你已經(jīng)為那個屬性提供了定制的 setter旦袋,那么你在 setter 中就可以觀察到任何值變化了。
防止重寫?
你可以通過把方法它改,屬性或下標(biāo)標(biāo)記為?final?來防止它們被重寫疤孕,只需要在聲明關(guān)鍵字前加上?final修飾符即可(例如:final var、final func央拖、final class func?以及?final subscript)祭阀。
任何試圖對帶有?final?標(biāo)記的方法鹉戚、屬性或下標(biāo)進(jìn)行重寫的代碼,都會在編譯時會報錯专控。在類擴(kuò)展中的方法抹凳,屬性或下標(biāo)也可以在擴(kuò)展的定義里標(biāo)記為?final。
可以通過在關(guān)鍵字?class?前添加?final?修飾符(final class)來將整個類標(biāo)記為 final 伦腐。這樣的類是不可被繼承的赢底,試圖繼承這樣的類會導(dǎo)致編譯報錯。
構(gòu)造過程:
構(gòu)造過程是使用類柏蘑、結(jié)構(gòu)體或枚舉類型的實(shí)例之前的準(zhǔn)備過程幸冻。在新實(shí)例使用前有個過程是必須的,它包括設(shè)置實(shí)例中每個存儲屬性的初始值和執(zhí)行其他必須的設(shè)置或構(gòu)造過程咳焚。
通過定義構(gòu)造器來實(shí)現(xiàn)構(gòu)造過程洽损。
與 Objective-C 中的構(gòu)造器不同,Swift 的構(gòu)造器沒有返回值革半。它們的主要任務(wù)是保證某種類型的新實(shí)例在第一次使用前完成正確的初始化碑定。
類和結(jié)構(gòu)體在創(chuàng)建實(shí)例時,必須為所有存儲型屬性設(shè)置合適的初始值又官。存儲型屬性的值不能處于一個未知的狀態(tài)延刘。你可以在構(gòu)造器中為存儲型屬性設(shè)置初始值,也可以在定義屬性時分配默認(rèn)值赏胚。以下小節(jié)將詳細(xì)介紹這兩種方法访娶。
構(gòu)造器 :構(gòu)造器在創(chuàng)建某個特定類型的新實(shí)例時被調(diào)用。它的最簡形式類似于一個不帶任何形參的實(shí)例方法觉阅,以關(guān)鍵字?init?命名:
init () {
? ? ? ? //在此執(zhí)行構(gòu)造過程
}
如果一個屬性總是使用相同的初始值崖疤,那么為其設(shè)置一個默認(rèn)值比每次都在構(gòu)造器中賦值要好。兩種方法的最終結(jié)果是一樣的典勇,只不過使用默認(rèn)值讓屬性的初始化和聲明結(jié)合得更緊密劫哼。
注意,如果不通過實(shí)參標(biāo)簽傳值割笙,這個構(gòu)造器是沒法調(diào)用的权烧。如果構(gòu)造器定義了某個實(shí)參標(biāo)簽,就必須使用它伤溉,忽略它將導(dǎo)致編譯期錯誤:
如果你不希望構(gòu)造器的某個形參使用實(shí)參標(biāo)簽般码,可以使用下劃線(_)來代替顯式的實(shí)參標(biāo)簽來重寫默認(rèn)行為。
可選屬性類型 :如果你自定義的類型有一個邏輯上允許值為空的存儲型屬性——無論是因?yàn)樗鼰o法在初始化時賦值乱顾,還是因?yàn)樗谥竽硞€時機(jī)可以賦值為空——都需要將它聲明為?可選類型板祝。可選類型的屬性將自動初始化為?nil走净,表示這個屬性是特意在構(gòu)造過程設(shè)置為空券时。
構(gòu)造過程中常量屬性的賦值 :你可以在構(gòu)造過程中的任意時間點(diǎn)給常量屬性賦值孤里,只要在構(gòu)造過程結(jié)束時它設(shè)置成確定的值。一旦常量屬性被賦值橘洞,它將永遠(yuǎn)不可更改捌袜。
注意:對于類的實(shí)例來說,它的常量屬性只能在定義它的類的構(gòu)造過程中修改炸枣;不能在子類中修改虏等。
結(jié)構(gòu)體的逐一成員構(gòu)造器 :結(jié)構(gòu)體如果沒有定義任何自定義構(gòu)造器,它們將自動獲得一個逐一成員構(gòu)造器(memberwise initializer)适肠。不像默認(rèn)構(gòu)造器博其,即使存儲型屬性沒有默認(rèn)值,結(jié)構(gòu)體也能會獲得逐一成員構(gòu)造器迂猴。
如果你為某個值類型定義了一個自定義的構(gòu)造器,你將無法訪問到默認(rèn)構(gòu)造器(如果是結(jié)構(gòu)體背伴,還將無法訪問逐一成員構(gòu)造器)沸毁。這種限制避免了在一個更復(fù)雜的構(gòu)造器中做了額外的重要設(shè)置,但有人不小心使用自動生成的構(gòu)造器而導(dǎo)致錯誤的情況傻寂。
值類型的構(gòu)造器代理 :構(gòu)造器可以通過調(diào)用其它構(gòu)造器來完成實(shí)例的部分構(gòu)造過程息尺。這一過程稱為構(gòu)造器代理,它能避免多個構(gòu)造器間的代碼重復(fù)疾掰。
類的繼承和構(gòu)造過程 :類里面的所有存儲型屬性——包括所有繼承自父類的屬性——都必須在構(gòu)造過程中設(shè)置初始值搂誉。
Swift 為類類型提供了兩種構(gòu)造器來確保實(shí)例中所有存儲型屬性都能獲得初始值,它們被稱為指定構(gòu)造器和便利構(gòu)造器静檬。
指定構(gòu)造器是類中最主要的構(gòu)造器炭懊。一個指定構(gòu)造器將初始化類中提供的所有屬性,并調(diào)用合適的父類構(gòu)造器讓構(gòu)造過程沿著父類鏈繼續(xù)往上進(jìn)行拂檩。
便利構(gòu)造器是類中比較次要的侮腹、輔助型的構(gòu)造器胚委。你可以定義便利構(gòu)造器來調(diào)用同一個類中的指定構(gòu)造器毫别,并為部分形參提供默認(rèn)值魄缚。你也可以定義便利構(gòu)造器來創(chuàng)建一個特殊用途或特定輸入值的實(shí)例霞扬。
指定構(gòu)造器和便利構(gòu)造器的語法?
類的指定構(gòu)造器的寫法跟值類型簡單構(gòu)造器一樣:
init (parameters){
? ? ? ?statements
}
便利構(gòu)造器也采用相同樣式的寫法撒顿,但需要在?init?關(guān)鍵字之前放置?convenience?關(guān)鍵字芥备,并使用空格將它們倆分開:
convenience init (parameters) {
? ? ? ? ?statements
}
類類型的構(gòu)造器代理?
為了簡化指定構(gòu)造器和便利構(gòu)造器之間的調(diào)用關(guān)系塞耕,Swift 構(gòu)造器之間的代理調(diào)用遵循以下三條規(guī)則:
規(guī)則 1
????指定構(gòu)造器必須調(diào)用其直接父類的的指定構(gòu)造器儡羔。
規(guī)則 2
便利構(gòu)造器必須調(diào)用同類中定義的其它構(gòu)造器煤篙。
規(guī)則 3
????便利構(gòu)造器最后必須調(diào)用指定構(gòu)造器斟览。
一個更方便記憶的方法是:
指定構(gòu)造器必須總是向上代理
便利構(gòu)造器必須總是橫向代理
構(gòu)造器的繼承和重寫 :跟 Objective-C 中的子類不同,Swift 中的子類默認(rèn)情況下不會繼承父類的構(gòu)造器舰蟆。Swift 的這種機(jī)制可以防止一個父類的簡單構(gòu)造器被一個更精細(xì)的子類繼承趣惠,而在用來創(chuàng)建子類時的新實(shí)例時沒有完全或錯誤被初始化狸棍。
可失敗構(gòu)造器:這里所指的“失敗” 指的是,如給構(gòu)造器傳入無效的形參味悄,或缺少某種所需的外部資源草戈,又或是不滿足某種必要的條件等。為了妥善處理這種構(gòu)造過程中可能會失敗的情況侍瑟。你可以在一個類唐片,結(jié)構(gòu)體或是枚舉類型的定義中,添加一個或多個可失敗構(gòu)造器涨颜。其語法為在?init?關(guān)鍵字后面添加問號(init?)费韭。可失敗構(gòu)造器會創(chuàng)建一個類型為自身類型的可選類型的對象庭瑰。你通過?return nil?語句來表明可失敗構(gòu)造器在何種情況下應(yīng)該 “失敗”星持。
注意
嚴(yán)格來說,構(gòu)造器都不支持返回值弹灭。因?yàn)闃?gòu)造器本身的作用督暂,只是為了確保對象能被正確構(gòu)造。因此你只是用?return nil?表明可失敗構(gòu)造器構(gòu)造失敗穷吮,而不要用關(guān)鍵字?return?來表明構(gòu)造成功逻翁。
枚舉類型的可失敗構(gòu)造器 :你可以通過一個帶一個或多個形參的可失敗構(gòu)造器來獲取枚舉類型中特定的枚舉成員。如果提供的形參無法匹配任何枚舉成員捡鱼,則構(gòu)造失敗八回。
帶原始值的枚舉類型的可失敗構(gòu)造器 :帶原始值的枚舉類型會自帶一個可失敗構(gòu)造器?init?(rawValue:),該可失敗構(gòu)造器有一個合適的原始值類型的?rawValue?形參驾诈,選擇找到的相匹配的枚舉成員缠诅,找不到則構(gòu)造失敗。
構(gòu)造失敗的傳遞 ::類翘鸭、結(jié)構(gòu)體滴铅、枚舉的可失敗構(gòu)造器可以橫向代理到它們自己其他的可失敗構(gòu)造器。類似的就乓,子類的可失敗構(gòu)造器也能向上代理到父類的可失敗構(gòu)造器汉匙。
無論是向上代理還是橫向代理,如果你代理到的其他可失敗構(gòu)造器觸發(fā)構(gòu)造失敗生蚁,整個構(gòu)造過程將立即終止噩翠,接下來的任何構(gòu)造代碼不會再被執(zhí)行。
必要構(gòu)造器 :在類的構(gòu)造器前添加?required?修飾符表明所有該類的子類都必須實(shí)現(xiàn)該構(gòu)造器:
class SomeClass {
? ? required init (){//構(gòu)造器的實(shí)現(xiàn)代碼}
}
在子類重寫父類的必要構(gòu)造器時邦投,必須在子類的構(gòu)造器前也添加?required?修飾符伤锚,表明該構(gòu)造器要求也應(yīng)用于繼承鏈后面的子類。在重寫父類中必要的指定構(gòu)造器時志衣,不需要添加?override?修飾符:
通過閉包或函數(shù)設(shè)置屬性的默認(rèn)值::如果某個存儲型屬性的默認(rèn)值需要一些自定義或設(shè)置屯援,你可以使用閉包或全局函數(shù)為其提供定制的默認(rèn)值猛们。每當(dāng)某個屬性所在類型的新實(shí)例被構(gòu)造時,對應(yīng)的閉包或函數(shù)會被調(diào)用狞洋,而它們的返回值會當(dāng)做默認(rèn)值賦值給這個屬性弯淘。
注意:閉包結(jié)尾的花括號后面接了一對空的小括號。這用來告訴 Swift 立即執(zhí)行此閉包吉懊。如果你忽略了這對括號庐橙,相當(dāng)于將閉包本身作為值賦值給了屬性,而不是將閉包的返回值賦值給屬性借嗽。
注意:如果你使用閉包來初始化屬性态鳖,請記住在閉包執(zhí)行時,實(shí)例的其它部分都還沒有初始化恶导。這意味著你不能在閉包里訪問其它屬性浆竭,即使這些屬性有默認(rèn)值。同樣惨寿,你也不能使用隱式的?self?屬性兆蕉,或者調(diào)用任何實(shí)例方法。
析構(gòu)過程
析構(gòu)器只適用于類類型缤沦,當(dāng)一個類的實(shí)例被釋放之前,析構(gòu)器會被立即調(diào)用易稠。析構(gòu)器用關(guān)鍵字?deinit來標(biāo)示缸废,類似于構(gòu)造器要用?init?來標(biāo)示。
析構(gòu)過程原理 :Swift 會自動釋放不再需要的實(shí)例以釋放資源驶社。如?自動引用計(jì)數(shù)?章節(jié)中所講述企量,Swift 通過自動引用計(jì)數(shù)(ARC)?處理實(shí)例的內(nèi)存管理。通常當(dāng)你的實(shí)例被釋放時不需要手動地去清理亡电。但是届巩,當(dāng)使用自己的資源時,你可能需要進(jìn)行一些額外的清理份乒。例如恕汇,如果創(chuàng)建了一個自定義的類來打開一個文件,并寫入一些數(shù)據(jù)或辖,你可能需要在類實(shí)例被釋放之前手動去關(guān)閉該文件瘾英。
在類的定義中,每個類最多只能有一個析構(gòu)器颂暇,而且析構(gòu)器不帶任何參數(shù)和圓括號缺谴,如下所示:
deinit { ?//執(zhí)行析構(gòu)過程
}
析構(gòu)器是在實(shí)例釋放發(fā)生前被自動調(diào)用的。你不能主動調(diào)用析構(gòu)器耳鸯。子類繼承了父類的析構(gòu)器湿蛔,并且在子類析構(gòu)器實(shí)現(xiàn)的最后膀曾,父類的析構(gòu)器會被自動調(diào)用。即使子類沒有提供自己的析構(gòu)器阳啥,父類的析構(gòu)器也同樣會被調(diào)用添谊。
因?yàn)橹钡綄?shí)例的析構(gòu)器被調(diào)用后,實(shí)例才會被釋放苫纤,所以析構(gòu)器可以訪問實(shí)例的所有屬性碉钠,并且可以根據(jù)那些屬性可以修改它的行為(比如查找一個需要被關(guān)閉的文件)。
可選鏈?zhǔn)秸{(diào)用
可選鏈?zhǔn)秸{(diào)用是一種可以在當(dāng)前值可能為?nil?的可選值上請求和調(diào)用屬性卷拘、方法及下標(biāo)的方法喊废。如果可選值有值,那么調(diào)用就會成功栗弟;如果可選值是?nil污筷,那么調(diào)用將返回?nil。多個調(diào)用可以連接在一起形成一個調(diào)用鏈乍赫,如果其中任何一個節(jié)點(diǎn)為?nil瓣蛀,整個調(diào)用鏈都會失敗,即返回?nil雷厂。
可選鏈?zhǔn)秸{(diào)用可以在空值(nil)上調(diào)用的事實(shí)惋增,不論這個調(diào)用的屬性、方法及下標(biāo)返回的值是不是可選值改鲫,它的返回結(jié)果都是一個可選值诈皿。你可以利用這個返回值來判斷你的可選鏈?zhǔn)秸{(diào)用是否調(diào)用成功,如果調(diào)用有返回值則說明調(diào)用成功像棘,返回?nil?則說明調(diào)用失敗稽亏。
這里需要特別指出,可選鏈?zhǔn)秸{(diào)用的返回結(jié)果與原本的返回結(jié)果具有相同的類型缕题,但是被包裝成了一個可選值
1.如果你訪問的值不是可選的截歉,可選鏈?zhǔn)秸{(diào)用將會返回可選值。
2.如果你訪問的值就是可選的烟零,可選鏈?zhǔn)秸{(diào)用不會讓可選返回值變得“更可選”瘪松。
因此:
3.通過可選鏈?zhǔn)秸{(diào)用訪問一個?Int?值,將會返回?Int?锨阿,無論使用了多少層可選鏈?zhǔn)秸{(diào)用凉逛。
4.類似的,通過可選鏈?zhǔn)秸{(diào)用訪問?Int??值群井,依舊會返回?Int??值状飞,并不會返回?Int??。