一、類的深入研究
(一)類的本質
類本身也是一個對象,是class類型的對象,簡稱“類對象”。
Class類型的定義:
Typedef?struct?obj?class?*class;
類名就代表著類對象,每個類只有一個類對象。
利用class?創建?Person類
利用Person?創建Person類型的對象
Person?*p=[[Person?alloc]?init];
?
獲取內存中的類對象有兩種方法:
(1)class?c=[p?claa];//指向類的對象的指針調用class方法
(2)Class?c1=[Person?class];//使用類名調用class方法
注意:c和c1打印出來的地址相同,class?c2=[p?claa];可以證明所有的對象共用一個類方法。
(二)類的加載和初始化
?
1.當程序啟動時,就會加載項目中所有的類和分類,而且加載后會調用每個類和分類的+load方法,只會調用一次;
2.當第一次使用某個類時,就會調用當前類的+initialize方法;
3.先加載父類,再加載子類(先調用父類的+load方法,再調用子類的+load方法,最后調用分類的+load方法),先初始化父類,再初始化子類(先調用父類的+initialize方法,再調用子類的+initialize方法)。
4.注意:在初始化的時候,如果在分類中重寫了+initialize方法,則會覆蓋掉父類的。
5.重寫+initialize方法可以監聽類的使用情況。
二、description方法
description方法包括類方法和對象方法。(NSObject類所包含)
(一)基本知識
-description(對象方法)
使用NSLog和@%輸出某個對象時,會調用對象的description方法,并拿到返回值進行輸出。
+description(類方法)
使用NSLog和@%輸出某個對象時,會調用類對象的description方法,并拿到返回值進行輸出,把整個對象一次性打印出來,打印對象使用%@。
使用@%打印對象如(“@%”,P)默認打印輸出為<類名:內存地址>,雖然字符串也是對象,但字符串在使用@%打印時情況特殊。
?
那么應該怎么實現打印對象的所有屬性呢?在類的實現中重寫description方法。
(二)實現打印對象的所有屬性
?
(三)區別
+description方法決定了類對象的輸出結果,即類本身
-description方法決定了實例對象的輸出結果,即Person創建的對象。
(四)打印相關補充
?
三、SEL
SEL:全稱Selector?表示方法的存儲位置。
方法在內存中是怎么存儲的?
?
Person?*p=[[Person?alloc]?init];
[p?test];
尋找方法的過程:
(1)首先把test這個方法名包裝成sel類型的數據;
(2)根據SEL數據找到對應的方法地址;
(3)根據方法地址調用相應的方法。
(4)注意:在這個操作過程中有緩存,第一次找的時候是一個一個的找,非常耗性能,之后再用到的時候就直接使用。
關于_cmd:每個方法的內部都有一個-cmd,代表著當前方法。
?
注意:SEL其實是對方法的一種包裝,將方法包裝成一個SEL類型的數據,去尋找對應的方法地址,找到方法地址后就可以調用方法。這些都是運行時特性,發消息就是發送SEL,然后根據SEL找到地址,調用方法。