類和元類
Objective-C
是一中類基礎的對象系統。每一個類都是類的實例,對象的isa
指針指向它所屬的類。類描述了對象的數據:分配的大小和實例變量類型以及布局形式。類也定義了對象的行為:選擇器去應答實現的實例方法。類的方法列表是一簇實例方法,對象可以應答的選擇器。當你給一個實例發送消息,objc_msgSend()
檢索對象的類(或父類)的方法列表決定調用哪個方法。
每個類也是一個對象,它有一個isa
指針和其他數據,然后也可以應答選擇器。當你調用一個類方法,就像[NSObject alloc]
,你實質上是給類對象發送了一個消息。
因為類是一個對象,它必須是某個另外的類的實例:一個元類。元類是一個類對象的描述,就像類是一個普通對象的描述。通常,元類的方法列表就是類方法:類對象選擇器可以應答。當你發送一個消息給一個類(一個元類的實例),objc_msgSend()
檢索元類(或其父類)的方法列表,決定調用哪個方法。元類為類對象描述了類方法,就像是類為實例對象描述類方法。
那么什么是元類呢?元類一直是啥呢?不,一個元類就是一個根類的元類的實例;這個根元類就是根元類實例自身。isa
鏈最后是循環的:實例指向類、類指向元類、元類指向根元類、根元類又指向實例本身。這種元類指針的行為極其罕見,因此真實世界沒有人發送消息給元類對象。
更重要的是元類的父類,元類的父類鏈與類的父類鏈平行,因此類方法伴隨著實例方法被繼承。同時根元類的父類就是根類,所以每個類對象都應答根類的實例方法。最后,一個類對象是一個根類的實例,和其他對象一樣。
迷糊了吧?這幅圖可能有用。記住,當一個消息發送給任何對象,這個方法檢索的開始是對象的isa
指針,然后繼續檢索父類鏈。實例方法是被類定義的,同時類方法是通過元類加上根類(不是元類)定義的。
在嚴格的計算機語言學中,一個類和元類的制定可以是任意形式,通過深層次的元類鏈和眾多來自單一元類的實例化的類。Objective-C
使用元類實際目的是:譬如類方法,但是其他時候都挺向于隱藏元類。例如[NSObject class]
跟[NSObject self]
一樣,盡管實際的元素應該返回NSObject->isa
指向的元類。Objective-C
語言是結合實際的折中組合;在獲取更多的元之前,它限制獲了類模式。