分類,多繼承

談?wù)勀銓Ψ诸怌ategory的理解

使用場景:可以減少單個文件體積;可以按照功能分組,放到不同的分類里,使結(jié)構(gòu)更清晰;降低耦合性,一個類可以有多個開發(fā)人員進(jìn)行開發(fā);模擬多繼承。

Category的實現(xiàn)原理:Category編譯之后的底層結(jié)構(gòu)是結(jié)構(gòu)體 category_t ,里面存儲著分類的對象方法、類方法、屬性、協(xié)議等信息。在程序運(yùn)行的時候,runtime會將category中的數(shù)據(jù),合并到類信息中(類對象、元類對象)


Category與 Extension的區(qū)別是什么:

1、Category 原則上只能增加方法,能添加屬性但是需要配合runtime才能解決沒有setter和getter的問題,這一點(diǎn)前文中有說明,下文中等下也再提一下。

2、Extension不僅可以添加方法,還可以增加屬性,只是屬性默認(rèn)的訪問權(quán)限是private。

3、Extension 中生命的方法沒有在.m 文件中實現(xiàn),編譯器會報警,但是在Category中的方法沒有實現(xiàn),編譯器沒有任何警告。這是因為Extension是在編譯階段添加到類中的,而Category是在運(yùn)行時添加到類中的。

如何通過Category實現(xiàn)多繼承?

比如有TestA和TestB兩個類,如圖


現(xiàn)在想實現(xiàn)一個TestC,讓TestC同時繼承TestA,和TestB。實現(xiàn)如下




測試結(jié)果如下


以上是通過分類的方式。還可以通過消息轉(zhuǎn)發(fā)的方式:(先注釋掉分類中的所有代碼,再加消息轉(zhuǎn)發(fā)代碼)


這里方法簽名、和forwardInvocation的方式我就不展示了,之前的文章中有講過

測試結(jié)果:


可以看到。我們在調(diào)用c 執(zhí)行playBasketBall和playFootBall時,其實調(diào)用到的是A 和B的方法。這里拋一個問題出來,假設(shè)我在消息轉(zhuǎn)發(fā)時這樣寫:把setAge:? age這些也加到消息轉(zhuǎn)發(fā)里,那么,外面在給C設(shè)置age的時候,調(diào)用的是誰的set方法、get方法?

答案是,調(diào)用c自己的set方法,因為進(jìn)入消息轉(zhuǎn)發(fā)前,需要先經(jīng)過消息發(fā)送、動態(tài)方法解析。 當(dāng)c本身就有setAge方法時,在消息發(fā)送階段就可以找到自己的setAge,直接調(diào)用自己的setter了,根本走不到消息轉(zhuǎn)發(fā)這個環(huán)節(jié)來。

當(dāng)然上述兩個方法應(yīng)該也可以配合使用,有興趣可以自己寫demo試試。

還有什么方式可以實現(xiàn)呢?

比如組合拳,C 先繼承A,然后C再強(qiáng)引用一個B的對象,這樣不管是調(diào)A的方法還是B的方法,都可以。

再比如協(xié)議,把A、B中需要繼承的方法,寫到協(xié)議里,然后C遵循這兩個協(xié)議,就可以在C中擁有A、B的方法了。

有興趣可以寫demo試試

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

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