Category支援新增成員變數

2021-07-27 08:55:49 字數 3317 閱讀 9371

一 . 類別的作用?

分類(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來...