OC 類似于C++ protected的解決方案

有時候我們需要對象沒有訪問權(quán)限,但是子類有訪問權(quán)限的設(shè)計,在C++里,有個protected限制符,可以解決這個問題。其實OC也有這個,@protected (@interface 成員變量默認的修飾符),但是OC有個限制,就是不能加入方法,只能使用成員變量。

當然,往這個方向發(fā)散下去,使用組合也是能解決問題的,例如



這個其實也是用了C++的方式去解決。

有沒有辦法用OC的方案去解決這個問題,答案是肯定的。首先,我們先明確兩個點,第一:頭文件的定義與實現(xiàn)沒有太大的關(guān)系,編譯器在連接的時候主要是對實現(xiàn)文件連接,所以說你頭文件在那定義,以及實現(xiàn)文件在那,沒有關(guān)聯(lián)性,你可以定義在A.h,然后在B.m去實現(xiàn)它。第二:interface 關(guān)鍵字一直都是接口(不是類,Go語言也是這樣的)的意思?;谶@兩點, 我們可以定義一個私有文件,然后在這個文件里聲明接口,并且只在另外一個文件.m里面去實現(xiàn)(對外面是隱藏的),然后在他的子類里面去,基于這個想法,有三種方案1.category(也稱為非正式協(xié)議),2.extension
(匿名類別或者類擴展),3.protocol(duck type)

1.category

注意點:


如果多個相同源類有相同的方法名或者跟基類的方法名一樣,會導(dǎo)致不可預(yù)知的問題。事實上,category的方法并沒有“完全替換掉”原來類已經(jīng)有的方法,也就是說如果category和原來類都有methodA,那么category附加完成之后,類的方法列表里會有兩個methodA,category的方法被放到了新方法列表的前面,而原來類的方法被放到了新方法列表的后面,這也就是我們平常所說的category的方法會“覆蓋”掉原來類的同名方法,這是因為運行時在查找方法的時候是順著方法列表的順序查找的,它只要一找到對應(yīng)名字的方法,就會return,后面可能還有一樣名字的方法。有興趣的可以看下objc-runtime-new.m的代碼(開源的)。

2.protocol


3.extension


注意點:


extension看起來很像一個匿名的category,但是extension和有名字的category幾乎完全是兩個東西。 extension在編譯期決議,它就是類的一部分,在編譯期和頭文件里的@interface以及實現(xiàn)文件里的@implement一起形成一個完整的類,它伴隨類的產(chǎn)生而產(chǎn)生,亦隨之一起消亡。extension一般用來隱藏類的私有信息,你必須有一個類的源碼才能為一個類添加extension,所以你無法為系統(tǒng)的類比如NSString添加extension。但是category則完全不一樣,它是在運行期決議的。就category和extension的區(qū)別來看,我們可以推導(dǎo)出一個明顯的事實,extension可以添加實例變量,而category是無法添加實例變量的(因為在運行期,對象的內(nèi)存布局已經(jīng)確定,如果添加實例變量就會破壞類的內(nèi)部布局,這對編譯型語言來說是災(zāi)難性的)。

從以上三個方案可以得出:如果你有屬性的話,category 和 potocol 都需要你自己去實現(xiàn)setter and getter ,而extension 就不需要。而且你如果基類,沒有實現(xiàn)方法,是沒有警告的,如果子類去調(diào)用沒有實現(xiàn)的方法就會崩潰 。而且extension 相當于編譯的時候已經(jīng)把他加入到他相應(yīng)的類里,如果方法沒有實現(xiàn),xcode 是有警告的。綜上所述,extension 是最完美的解決方案。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容