分類不能直接添加成員變量,可以通過關(guān)聯(lián)對象間接達(dá)到添加成員變量的效果,不能添加成員變量是由于分類的底層結(jié)構(gòu)體是這樣的

分類里面有實例方法列表、類方法列表、協(xié)議列表、實例屬性列表、類屬性列表,沒有成員變量列表,類似ivars的變量,所以分類中不能添加成員變量,下面通過代碼看下


上圖可以看出,給類WPPerson添加了一個分類,然后定義了一個name屬性,在getter方法中使用_name成員變量是報錯的
其實也可以手動實現(xiàn)有成員變量的假象,讓外部使用起來沒有什么感覺,做法是定義一個全局字典,將外部調(diào)用setter方法傳進(jìn)來的數(shù)據(jù)保存在字典中,大家可以自己嘗試下。
下面說下關(guān)聯(lián)對象的使用,關(guān)聯(lián)對象主要是通過調(diào)用兩個方法來實現(xiàn)

先說下這幾個參數(shù):
參數(shù)1:需要關(guān)聯(lián)的對象,傳self
參數(shù)2:key,這是一個void*,所以傳一個地址進(jìn)去
參數(shù)3:value,外部傳入的值
參數(shù)4:關(guān)聯(lián)存儲策略,和我們平時修飾屬性時一樣,copy,strong,assign,nonatomic。。。
用法很簡單,由于在分類中添加屬性,系統(tǒng)只會生成該屬性的setter和getter方法的申明,所以需要自己寫實現(xiàn)


這樣外部在使用時和在類里面定義的屬性就沒有什么區(qū)別,但底層實現(xiàn)和直接在類里面定義的屬性是不一樣的,下面通過源碼看下關(guān)聯(lián)對象的底層實現(xiàn)


主要實現(xiàn)在_object_set_associative_reference方法里面,先說下這幾個類的關(guān)系




AssociationsManager:管理者
AssociationsHashMap:里面存儲著所有關(guān)聯(lián)對象的信息,一個鍵值就是一個關(guān)聯(lián)對象的信息(WPPerson、WPCat。。。)
AssociationsHashMap:里面存儲著當(dāng)前WPPerson關(guān)聯(lián)對象的所有關(guān)聯(lián)屬性信息,一個鍵值就是一個屬性信息(name、age。。)
ObjectAssociation:里面存儲著當(dāng)前屬性的關(guān)聯(lián)策略以及具體的值
這樣一層層的就能找到對應(yīng)的關(guān)聯(lián)信息,比如我們想獲取WPPerson的name屬性的值時,先找到AssociationsManager里面的AssociationsHashMap,再通過WPPerson的實例作為key從AssociationsHashMap找到對應(yīng)的value也就是AssociationsHashMap,再通過name的key也就是@selector(name)最為key從AssociationsHashMap中找到ObjectAssociation,這樣就能拿到name屬性的具體值了
下面給源碼添加了注釋

清除關(guān)聯(lián)對象只需要調(diào)用方法的時候?qū)alue傳入nil即可
所以關(guān)聯(lián)對象底層其實是用一個全局的hashMap將self與所謂的成員變量保存起來,并不是存在類對象或者元類對象里面