Objective-C是基於類的物件導向語言。每個對象都是某個類的一個執行個體對象;對象的isa指標指向了對象對應的類。類描述了對象的資料:記憶體配置大小和變數(ivar)類型和布局。類也描述了對象的行為:類能夠響應的選取器(selectors按字面翻譯是因為selector並不是方法的具體實現的起始地址而是作為一個key對應存放著方法的起始地址)和類實現的具體方法。
類的方法列表是方法執行個體、對象能夠響應的選取器的集合。當你發送一個方法給一個執行個體對象的時候,objc_msgSend()查詢對象對應的類的方法列表(如果有超類的話,也查詢超類的方法列表)來決定具體調用哪個方法。
每一個Objective-C類也是一個對象。他也有一個isa指標和其他的資料,和可以相應的選取器。當你調用一個“類方法的時候”例如[NSObject alloc],確實是給類對象(不是類的執行個體對象)發送了一個訊息。
既然類也是一個對象,它一定也是一個其他類的執行個體:原類。原類是類對象的描述,就像是類是原始執行個體對象的描述一樣。特別是,原類的方法列表是類的方法:類對象可以相應的選取器。當你發送一個訊息給一個類-原類的執行個體- objc_msgSend()查詢原類的方法列表(如果有超類的話,也查詢超類的方法列表)來決定具體調用什麼方法。類方法是由代表類對象的原類來描述的。就像對象執行個體方法是由代表執行個體對象的類來描述的一樣。
那原類呢?原類就是最深層的實現嗎?不是的,原類是root類的原類的執行個體;root原類是它自身的一個執行個體。這個isa傳遞就在這終結:對象執行個體—類—原類—root原類—root原類自身。原類的isa指標的行為是沒有多大關係的,一般很少有人給原類對象發送訊息的。
更重要的是原類的超類。原類的超類鏈是和類的超類鏈並行的,所以類方法也是和執行個體方法並行的。Root原類的超類是root類,所以每個類對象可以相應root類執行個體的方法。最後,類對象是root類(或者是子類)的執行個體,就像任何其他對象一樣。
迷糊了嗎?下面的圖將幫你理解。記住,當一個訊息被發送到任何對象的時候,方法查詢是從對象的isa指標開始的,然後從超類鏈繼續查詢。“執行個體方法”是由類定義的,“類方法”是由原類加上root類(非原)定義的。
在恰當的電腦科學語言理論中,類和原類的階層是可以更加自由的,有更深的原類鏈和從任何簡單的原類執行個體化出多個類。Objective-C為了實際目標像類方法一樣使用原類,但是又要隱藏原類。例如,[NSObject class]是和[NSObject self]相等的,雖然形式上它應該返回NSObject->isa指向的原類。Objective-C語言是一個折中的集合;在獲得too、well、meta之前限制了類的架構。
原文連結:http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html