一 . 類別的作用?
分類(category)是有名稱的,分類可以在不修改原來類模型的基礎上拓充方法,不能擴充成員變數;
3個作用:
(1)將類的實現分散到多個不同檔案或多個不同框架中。並且如果類別和原來類中的方法產生名稱衝突,則類別將覆蓋原來的方法,因為類別具有更高的優先順序。分類依賴類而存在,沒有類也就沒有分類
(2)建立對私有方法的前向引用。
(3)模擬多繼承
(4)把framework的私有方法公開
二 . 繼承和類別在實現中有何區別? 重寫乙個類的方式用繼承好還是分類好?為什麼?
繼承 乙個類繼承另乙個類,就是繼承了父類所有的屬性和方法,可以擴充,修改或者刪除方法和擴充成員變數; 繼承會產生新的類
category是類別,一般情況用分類好,用category去重寫類的方法,僅對本category有效,不會影響到其他類與原有類的關係。
category只能為物件新增方法,卻不能新增成員變數的原因:如果可以新增成員變數,
新增的成員變數沒有辦法初始化——這是語言規則 >.難以維護 >.難以使用
三 . 與extension的比較
類擴充套件(extensions)沒有名稱,類擴充套件可以擴充方法和成員變數.類擴充套件新增的方法是必須要實現的。extension是編譯器決議,和類的標頭檔案裡的@inte***ce以及實現檔案裡面的@implement一起形成乙個完整的類。你必須用乙個類的原始碼才能為它extension,比如你無法為nsstring新增extension。
extensions可以認為是乙個私有的category。類擴充套件一般就寫在.m檔案中,用來擴充私有的方法和成員變數(屬性/例項變數)因此,
根據開發需求
,如果這個類需要擴充屬性
,或者需要重寫系統的類的某些方法
,用繼承
;如果只是對乙個類擴充介面和模組
,使用類別更加方便。
category是執行期決議的。而category作為執行期決議是無法新增例項變數,因為會破壞類的記憶體布局。
注意 : 1.分類中能否訪問原類中的成員變數?
要訪問原類中屬性的直接用self.***就行了,前提是原類中的***是定義在介面處
2.分類中
不能使用self關鍵字
四 .執行時的category
執行時,oc幾乎所有的內容都是以結構體的形式存在的。catrgory也不例外。
typedef struct category_t category_t;
1)、類的名字(name)
2)、類(cls)
3)、category中所有給類新增的例項方法的列表(instancemethods)
4)、category中所有新增的類方法的列表(classmethods)
5)、category實現的所有協議的列表(protocols)
6)、category中新增的所有屬性(instanceproperties)
結論:category並不是絕對的覆蓋了類的同名方法,而是catrgory的方法被排在了類的同名方法之前,而方法的檢索方式是順序檢索,所以在呼叫方法時,呼叫到的同名方法是category的,進而產生了覆蓋效果。
五 . 給category新增成員變數
乙個類的兩個category,如果存在方法名相同,是根據buildphases->compile sources裡面的從上至下順序編譯的,即後編譯的會被呼叫。
在xcode->edit scheme->run->arguments->environment variables中新增執行時環境變數可列印相應category載入訊息。
(更多變數在objc-private.h中)
下列**是利用執行時遍歷方法列表,呼叫被category覆蓋的方法:
class currentclass = [vvstack class];
vvstack * my = [vvstack new];
if (currentclass)
}typedef void (*functionn) (id, sel);
if (lastimp!= null)
//釋放方法列表
free(methodlist);
}
雖說category中無法直接新增屬性,但是我們在category中可以利用執行時新增屬性:
在category中使用@property也是只會生成setter和getter方法的宣告,如果我們真的需要給category增加屬性的實現,需要借助於執行時的兩個函式:
1)obj_setassociatedobject
2)obj_getassociatedobject
首先介紹一下@property,它的本質其實是ivar(例項變數)+ getter方法 + setter方法。
所以在category中重寫getter和setter方法,再新增乙個ivar的變數,就可以實現@property的功能了。
- (void)setname:(nsstring *)name
- (nsstring*)name
如此便可以在類中利用點語法呼叫name屬性。
以上**就實現了給category動態新增屬性。下面介紹這兩個方法
1,objc_setassociatedobject(id object, const void *key, id value, objc_associationpolicy policy)
這個函式需要四個引數:源物件,關鍵字,關聯的物件和乙個關聯策略。
@param object: 源物件 self
@param key: 唯一靜態變數key
@param value:關聯的物件
@param policy: 關聯政策,相當於屬性括號中的限定條件
typedef objc_enum(uintptr_t, objc_associationpolicy) ;
2,objc_getassociatedobject(id object, const void *key)
這個函式用於獲取關聯物件的結果。
@param object: 源物件 self
@param key: 唯一靜態變數key
利用以上的方法,就可以給category新增屬性了。
category新增成員變數
oc的category是乙個非常好用的特性,它允許你在不改變原始碼的情況下擴充套件類的一些功能特性,從而能更好地組織你地 但是使用category有乙個很大地限制,不能在category裡新增成員變數,這個限制較大地限制了category的使用,當然使用extension可以往類裡面新增成員變數,但...
OC category 為什麼不能新增成員變數
1.利用執行時實際上也不是新增成員變數。已編譯的類的記憶體布局是不變的,class就是乙個結構體,裡面的成員不能改變。但是通過執行時可以將乙個物件或基礎型別變成指定class物件的乙個關聯物件,他們兩者的記憶體布局是分開的,與成員變數不同。2.關聯的並不是在指定class上,而是指定的物件上,概念上...
Category支援新增屬性與成員變數
category是objective c中常用的語法特性,通過它可以很方便的為已有的類來新增函式。但是category不允許為已有的類新增新的屬性或者成員變數。一種常見的辦法是通過runtime.h中objc getassociatedobject objc setassociatedobject來...