OC中提供的category特性可以讓我們動(dòng)態(tài)的為現(xiàn)有類添加新的行為,以比繼承更為簡(jiǎn)潔的方法來(lái)對(duì)Class進(jìn)行擴(kuò)展,無(wú)需創(chuàng)建對(duì)象類的子類就能為現(xiàn)有的類添加新方法,它可以為任何已經(jīng)存在的Class添加方法,包括那些蘋果沒(méi)有公開源代碼的類。
category作用
可以將類的實(shí)現(xiàn)分散到多個(gè)不同的文件或者不同的框架中,方便代碼的管理,也可以對(duì)框架提供類的擴(kuò)展
創(chuàng)建對(duì)私有方法的前向引用:
Cocoa沒(méi)有任何真正的私有方法。只要知道對(duì)象支持的某個(gè)方法的名稱,即使該對(duì)象所在的類的接口中沒(méi)有該方法的聲明,你也可以調(diào)用該方法。不過(guò)這么做編譯器會(huì)報(bào)錯(cuò),但是只要新建一個(gè)該類的類別,在類別.h文件中寫上原始類該方法的聲明,類別.m文件中什么也不寫,就可以正常調(diào)用私有方法了。這就是傳說(shuō)中的私有方法前向引用。 所以說(shuō)cocoa沒(méi)有真正的私有方法。向?qū)ο筇砑臃钦絽f(xié)議:
蘋果官方文檔:
An informal protocol is a category on NSObject, which implicitly makes almost all objects adopters of the protocol. (A category is a language feature that enables you to add methods to a class without subclassing it.) Implementation of the methods in an informal protocol is optional. Before invoking a method, the calling object checks to see whether the target object implements it. Until optional protocol methods were introduced in Objective-C 2.0, informal protocols were essential to the way Foundation and AppKit classes implemented delegation.
也就是說(shuō):非正式協(xié)議是NSObject類(顯而易見,還包括它的子類)的類別,其所有的子類都含蓄地接受了這個(gè)協(xié)議。(類別是Objective-C的一個(gè)語(yǔ)言特點(diǎn),可以讓你在無(wú)需子類化的前提下為一個(gè)類增加方法。)非正式協(xié)議中的方法是否實(shí)現(xiàn)都是可選的,因此在調(diào)用非正式協(xié)議中的方法之前,需要去檢查對(duì)象類是否實(shí)現(xiàn)了它。在Objective-C2.0中引入可選的正式協(xié)議方法之前,非正式協(xié)議是Foundation和AppKit類實(shí)現(xiàn)委托的唯一方式。所謂的非正式協(xié)議就是類別,即凡是NSObject或其子類的類別,都是非正式協(xié)議。
category與extension的區(qū)別:
- extension和category的創(chuàng)建方式一樣,只要在原來(lái)選擇Category的地方選擇Extension即可。但是,extension只會(huì)生成 .h 文件。之后我們可以在.h中直接添加成員變量、屬性和方法。而category是不能直接添加成員變量的(需要使用runtime添加)extension的常用形式不是創(chuàng)建一個(gè)單獨(dú)的文件,而是在實(shí)現(xiàn)文件中添加私有的成員變量、屬性和方法(比如創(chuàng)建Controller的時(shí)候XCode會(huì)自動(dòng)生成)
- extension在編譯期決議,它就是類的一部分,在編譯期和頭文件里的@interface以及實(shí)現(xiàn)文件里的@implement一起形成一個(gè)完整的類,它伴隨類的產(chǎn)生而產(chǎn)生,亦隨之一起消亡。extension一般用來(lái)隱藏類的私有信息,你必須有一個(gè)類的源碼才能為一個(gè)類添加extension,所以你無(wú)法為系統(tǒng)的類比如NSString添加extension。
- 類別在運(yùn)行期決議的,就類別和擴(kuò)展的區(qū)別來(lái)看,我們可以推導(dǎo)出一個(gè)明顯的事實(shí),擴(kuò)展可以添加實(shí)例變量,而類別是無(wú)法添加實(shí)例變量的(因?yàn)樵谶\(yùn)行期,對(duì)象的內(nèi)存布局已經(jīng)確定,如果添加實(shí)例變量就會(huì)破壞類的內(nèi)部布局,這對(duì)編譯型語(yǔ)言來(lái)說(shuō)是災(zāi)難性的)。
category為什么不能添加實(shí)例變量但可以添加屬性?
我們知道Objective-C類是由Class類型來(lái)表示的,它實(shí)際上是一個(gè)指向objc_class結(jié)構(gòu)體的指針。所以類其實(shí)就是一個(gè)結(jié)構(gòu)體,類別也是一樣:
typedef struct category_t {
const char *name; // 類的名字(名稱)
classref_t cls; // 類(CLS)
struct method_list_t *instanceMethods; // 類中所有給類添加的實(shí)例方法的列表
struct method_list_t *classMethods; // 類中所有添加的類方法的列表
struct protocol_list_t *protocols; // category實(shí)現(xiàn)的所有協(xié)議的列表
struct property_list_t *instanceProperties; // category中添加的所有屬性
} category_t;
從類別的定義也可以看出類別的可以添加實(shí)例方法,類方法,甚至可以實(shí)現(xiàn)協(xié)議,添加屬性和不可以添加實(shí)例變量。