原文再續(xù),書(shū)折第一回。
很多其他編程語(yǔ)言都有一種”protected“設(shè)定,可以限制某些類(lèi)方法只能被它的子類(lèi)所使用。
Swift支持了訪(fǎng)問(wèn)控制后,大家給我們的反饋都很不錯(cuò)。而有的開(kāi)發(fā)者問(wèn)我們:“為什么Swift沒(méi)有類(lèi)似protected的選項(xiàng)?”
當(dāng)我們?cè)谠O(shè)計(jì)Swift訪(fǎng)問(wèn)控制的不同等級(jí)時(shí),我們認(rèn)為有兩種主要場(chǎng)景:
上面的兩種常見(jiàn)情況,對(duì)應(yīng)著private和internal這兩個(gè)等級(jí)。
而protected相當(dāng)于把訪(fǎng)問(wèn)控制和繼承特性混在一起,把訪(fǎng)問(wèn)控制的等級(jí)設(shè)定增加了一個(gè)維度,使之復(fù)雜化。即使設(shè)定了protected,子類(lèi)還是可以通過(guò)新的公開(kāi)方法、新的屬性來(lái)接觸到所謂“protected”了的API。另一方面,我們可以在各種地方重寫(xiě)一個(gè)方法,所謂的保護(hù)卻沒(méi)有提供優(yōu)化機(jī)制。這種設(shè)定往往在做不必要的限制 一 protected允許了子類(lèi),但又禁止所有其他別的類(lèi)(包括那些幫助子類(lèi)實(shí)現(xiàn)某些功能的類(lèi))接觸父類(lèi)的成員。
有的開(kāi)發(fā)者指出,apple的框架有時(shí)候也會(huì)把給子類(lèi)用的API分隔出來(lái)。這時(shí)候protected不就有用了嗎?我們研究后發(fā)現(xiàn),這些方法一般屬于下面兩種情況:一是這些方法對(duì)子類(lèi)以外的類(lèi)沒(méi)啥用,所以不需要嚴(yán)格保護(hù)(例如上面說(shuō)的協(xié)助實(shí)現(xiàn)某些功能的類(lèi))。二是這些方法就是設(shè)計(jì)出來(lái)被重寫(xiě),而不是直接用的。舉個(gè)例子,drawRect(_:)
就是在UIKit基礎(chǔ)上使用的方法,但它不能在UIKit以外應(yīng)用。
除此之外,如果有了protected,它要怎么樣和extension相互作用呢?一個(gè)類(lèi)的extension能接觸它的protected成員嗎?一個(gè)子類(lèi)的extension可以接觸父類(lèi)的protected成員嗎?extension聲明的位置對(duì)訪(fǎng)問(wèn)控制等級(jí)有沒(méi)有影響呢?(復(fù)雜到要哭了是不是?)
對(duì)訪(fǎng)問(wèn)控制的設(shè)計(jì),也依循了Objective-C開(kāi)發(fā)者(包括apple內(nèi)外的)的常規(guī)做法。Objective-C方法和屬性一般在.h頭文件里聲明,但也可以寫(xiě)在.m實(shí)現(xiàn)文件里。假如有一個(gè)公開(kāi)的類(lèi),想把里面某些部分設(shè)為只有框架內(nèi)可以獲取時(shí),開(kāi)發(fā)者一般會(huì)創(chuàng)建另一個(gè)頭文件給內(nèi)部使用。以上三種訪(fǎng)問(wèn)級(jí)別,就對(duì)應(yīng)了Swift里面的public,private和internal。
Swift的訪(fǎng)問(wèn)控制等級(jí)和繼承無(wú)關(guān),是單維度、非常清楚明了的。我們認(rèn)為這樣的模式更簡(jiǎn)潔,同時(shí)滿(mǎn)足了最主要的需求:將一個(gè)類(lèi)、或一個(gè)框架的實(shí)現(xiàn)細(xì)節(jié)隔離保護(hù)起來(lái)。這可能和你以前用過(guò)的不同,但我們鼓勵(lì)你試試看。
本章節(jié)不是老碼的原創(chuàng),是老碼認(rèn)真的閱讀了蘋(píng)果的官方博客,自己的練習(xí)總結(jié),如果小伙伴們費(fèi)了吃奶的勁還是看不懂,請(qǐng)找度娘谷歌。還是看不懂?請(qǐng)到老碼官方微博咆哮。