swift 關(guān)鍵字 final

final

關(guān)鍵字可以用在,或者前面進(jìn)行修飾,表示不允許對(duì)該內(nèi)容進(jìn)行繼承或者重寫(xiě)操作。這個(gè)關(guān)鍵字的作用和C#中的相同,而其實(shí)在C#算是一個(gè)飽受爭(zhēng)議的關(guān)鍵字。有一派程序員認(rèn)為,類似這樣的禁止繼承和重寫(xiě)的做法是非常有益的,它可以更好地對(duì)代碼進(jìn)行版本控制,得到更佳的性能,以及使代碼更安全。因此他們甚至認(rèn)為語(yǔ)言應(yīng)當(dāng)是默認(rèn)不允許繼承的,只有在顯式地指明可以繼承的時(shí)候才能子類化。

在寫(xiě)Swift的時(shí)候可能會(huì)在什么情況下使用

權(quán)限控制

給一段代碼加上就意味著編譯器向你作出保證,這段代碼不會(huì)再被修改;同時(shí),這也意味著你認(rèn)為這段代碼已經(jīng)完備并且沒(méi)有再被進(jìn)行繼承或重寫(xiě)的必要,因此這往往會(huì)是一個(gè)需要深思熟慮的決定。在Cocoa開(kāi)發(fā)中app開(kāi)發(fā)是一塊很大的內(nèi)容,對(duì)于大多數(shù)我們自己完成的面向app開(kāi)發(fā)代碼,其實(shí)不太會(huì)提供給別人使用,這種情況下即使是將所有自己寫(xiě)的代碼標(biāo)記為都是一件無(wú)可厚非的事情(但我并不是在鼓勵(lì)這么做) --因?yàn)樵谛枰娜魏螘r(shí)候你都可以將這個(gè)關(guān)鍵字去掉以恢復(fù)其可繼承性。而在開(kāi)發(fā)給其他開(kāi)發(fā)者使用的庫(kù)時(shí),就必須更深入地考慮各種使用場(chǎng)景和需求了。

一般來(lái)說(shuō),不希望被繼承和重寫(xiě)會(huì)有這幾種情況:

類或者方法的功能確實(shí)已經(jīng)完備了

對(duì)于很多的輔助性質(zhì)的工具類或者方法,可能我們會(huì)考慮加上。這樣的類有一個(gè)比較大的特點(diǎn),是很可能只包含類方法而沒(méi)有實(shí)例方法。比如我們很難想到一種情況需要繼承或重寫(xiě)一個(gè)負(fù)責(zé)計(jì)算一段字符串的MD5或者AES加密解密的工具類。這種工具類和方法的算法是經(jīng)過(guò)完備驗(yàn)證和固定的,使用者只需要調(diào)用,而相對(duì)來(lái)說(shuō)不可能有繼承和重寫(xiě)的需求。

這種情況很多時(shí)候遵循的是以往經(jīng)驗(yàn)和主觀判斷,而單個(gè)的開(kāi)發(fā)者的判斷其實(shí)往往并不可靠。遇到希望把某個(gè)自己開(kāi)發(fā)的類或者方法標(biāo)為的時(shí)候,去找?guī)讉€(gè)富有經(jīng)驗(yàn)的開(kāi)發(fā)者,問(wèn)問(wèn)他們的意見(jiàn)或者看法,應(yīng)該是一個(gè)比較靠譜的做法。

子類繼承和修改是一件危險(xiǎn)的事情

在子類繼承或重寫(xiě)某些方法后可能做一些破壞性的事情,導(dǎo)致子類或者父類部分也無(wú)法正常工作的情況。舉個(gè)例子,在某個(gè)公司管理的系統(tǒng)中我們對(duì)員工按照一定規(guī)則進(jìn)行編號(hào),這樣通過(guò)編號(hào)我們能迅速找到任一員工。而假如我們?cè)谧宇愔兄貙?xiě)了這個(gè)編號(hào)方法,很可能就導(dǎo)致基類中的依賴員工編號(hào)的方法失效。在這類情況下,將編號(hào)方法標(biāo)記為以確保穩(wěn)定,可能是一種更好的做法。

為了父類中某些代碼一定會(huì)被執(zhí)行

有時(shí)候父類中有一些關(guān)鍵代碼是在被繼承重寫(xiě)后必須執(zhí)行的(比如狀態(tài)配置,認(rèn)證等等),否則將導(dǎo)致運(yùn)行時(shí)候的錯(cuò)誤。而在一般的方法中,如果子類重寫(xiě)了父類方法,是沒(méi)有辦法強(qiáng)制子類方法一定去調(diào)用相同的父類方法的。在Objective-C的時(shí)候我們可以通過(guò)指定__attribute__((objc_requires_super))這樣的屬性來(lái)讓編譯器在子類沒(méi)有調(diào)用父類方法時(shí)拋出警告。

在Swift中對(duì)原來(lái)的很多attribute的支持現(xiàn)在還缺失中,為了達(dá)到類似的目的,我們可以使用一個(gè)final的方法,在其中進(jìn)行一些必要的配置,然后再調(diào)用某個(gè)需要子類實(shí)現(xiàn)的方法,以確保正常運(yùn)行:

class ? ?Parent{

? ? ? final fun method() {?

? ? ? ? ? ? ? ? methodImpl()

? ? ? ?}

func methodImpl(){ fatalError("子類必須實(shí)現(xiàn)這個(gè)方法")}

}

class ?Child: Parent {

override ? func ?methodImpl(){ //..子類的業(yè)務(wù)邏輯}

}

這樣,無(wú)論如何我們?nèi)绾问褂茫伎梢员WC需要的代碼一定被運(yùn)行過(guò),而同時(shí)又給了子類繼承和重寫(xiě)自定義具體實(shí)現(xiàn)的機(jī)會(huì)。

性能考慮

使用final的另一個(gè)重要理由是可能帶來(lái)的性能改善。因?yàn)榫幾g器能夠從final中獲取額外的信息,因此可以對(duì)類或者方法調(diào)用進(jìn)行額外的優(yōu)化處理。但是這個(gè)優(yōu)勢(shì)在實(shí)際表現(xiàn)中可能帶來(lái)的好處其實(shí)就算與Objective-C的動(dòng)態(tài)派發(fā)相比也十分有限,因此在項(xiàng)目還有其他方面可以優(yōu)化(一般來(lái)說(shuō)會(huì)是算法或者圖形相關(guān)的內(nèi)容導(dǎo)致性能瓶頸)的情況下,并不建議使用將類或者方法轉(zhuǎn)為的方式來(lái)追求性能的提升。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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