轉(zhuǎn)載:對(duì)象之類對(duì)象和元類對(duì)象

Objective-C對(duì)象之類對(duì)象和元類對(duì)象(一)

作者:wangzz
原文地址:http://blog.csdn.net/wzzvictory/article/details/8592492
轉(zhuǎn)載請(qǐng)注明出處
如果覺(jué)得文章對(duì)你有所幫助富弦,請(qǐng)通過(guò)留言或關(guān)注微信公眾帳號(hào)wangzzstrive來(lái)支持我删咱,謝謝甘苍!

作為C語(yǔ)言的超集场仲,面向?qū)ο蟪蔀镺bjective-C與C語(yǔ)言的最大區(qū)別灸眼,因此评腺,對(duì)象是Objective-C中最重要的部分之一杈女。目前面向?qū)ο蟮恼Z(yǔ)言有很多夏漱,Objective-C中的對(duì)象又和其他語(yǔ)言中的對(duì)象有什么區(qū)別呢豪诲?下面來(lái)簡(jiǎn)單介紹Objective-C中對(duì)象的實(shí)現(xiàn)。1挂绰、Objective-C中的類誰(shuí)都知道屎篱,所有的對(duì)象都是由其對(duì)應(yīng)的類實(shí)例化而來(lái),殊不知類本身也是一種對(duì)象葵蒂,先不要對(duì)這句話感到驚訝交播。首先我們來(lái)關(guān)注objective-c中的類。在Objective-C中刹勃,我們用到的幾乎所有類都是NSObject類的子類堪侯,NSObject類定義格式如下(忽略其方法聲明):@interface NSObject <NSObject> {Class isa;}這個(gè)Class為何物嚎尤?在objc.h中我們發(fā)現(xiàn)其僅僅是一個(gè)結(jié)構(gòu)(struct)指針的typedef定義:typedef struct objc_class *Class;同樣的荔仁,objc_class又是什么呢?在Objective-C2.0中芽死,objc_class的定義如下:struct objc_class {Class isa;}寫到這里大家可能就暈了乏梁,怎么又有一個(gè)isa?关贵?這些isa到底是什么遇骑?之間有什么區(qū)別和聯(lián)系?接下來(lái)解答這一連串的疑問(wèn)揖曾。其實(shí)在Objective-C中任何的類定義都是對(duì)象落萎。即在程序啟動(dòng)的時(shí)候任何類定義都對(duì)應(yīng)于一塊內(nèi)存。在編譯的時(shí)候炭剪,編譯器會(huì)給每一個(gè)類生成一個(gè)且只生成一個(gè)”描述其定義的對(duì)象”,也就是蘋果公司說(shuō)的類對(duì)象(class object),他是一個(gè)單例(singleton), 而我們?cè)贑++等語(yǔ)言中所謂的對(duì)象练链,叫做實(shí)例對(duì)象(instance object)。對(duì)于實(shí)例對(duì)象我們不難理解奴拦,但類對(duì)象(class object)是干什么吃的呢媒鼓?我們知道Objective-C是門很動(dòng)態(tài)的語(yǔ)言,因此程序里的所有實(shí)例對(duì)象(instace object)都是在運(yùn)行時(shí)由Objective-C的運(yùn)行時(shí)庫(kù)生成的,而這個(gè)類對(duì)象(class object)就是運(yùn)行時(shí)庫(kù)用來(lái)創(chuàng)建實(shí)例對(duì)象(instance object)的依據(jù)绿鸣。再回到之前的問(wèn)題疚沐,腫么這個(gè)實(shí)例對(duì)象(instance object)的isa指針指向的類對(duì)象(class object)里面還有一個(gè)isa呢?這個(gè)類對(duì)象(class objec)的isa指向的依然是一個(gè)objc-class潮模,它就是“元類對(duì)象”(metaclass object)亮蛔,它和類對(duì)象(class object)的關(guān)系是這樣的:
2、類對(duì)象(class object)①類對(duì)象的實(shí)質(zhì)我們知道了:類對(duì)象是由編譯器創(chuàng)建的擎厢,即在編譯時(shí)所謂的類尔邓,就是指類對(duì)象(官方文檔中是這樣說(shuō)的: The class object is the compiled version of the class)。任何直接或間接繼承了NSObject的類锉矢,它的實(shí)例對(duì)象(instance objec)中都有一個(gè)isa指針梯嗽,指向它的類對(duì)象(class object)。這個(gè)類對(duì)象(class object)中存儲(chǔ)了關(guān)于這個(gè)實(shí)例對(duì)象(instace object)所屬的類的定義的一切:包括變量沽损,方法灯节,遵守的協(xié)議等等。因此绵估,類對(duì)象能訪問(wèn)所有關(guān)于這個(gè)類的信息炎疆,利用這些信息可以產(chǎn)生一個(gè)新的實(shí)例,但是類對(duì)象不能訪問(wèn)任何實(shí)例對(duì)象的內(nèi)容国裳。當(dāng)你調(diào)用一個(gè) “類方法” 例如 [NSObject alloc],你事實(shí)上是發(fā)送了一個(gè)消息給他的類對(duì)象形入。
②類對(duì)象和實(shí)例對(duì)象的區(qū)別當(dāng)然有區(qū)別了,盡管類對(duì)象保留了一個(gè)類實(shí)例的原型缝左,但它并不是實(shí)例本身亿遂。它沒(méi)有自己的實(shí)例變量,也不能執(zhí)行那些類的實(shí)例的方法(只有實(shí)例對(duì)象才可以執(zhí)行實(shí)例方法)渺杉。然而蛇数,類的定義能包含那些特意為類對(duì)象準(zhǔn)備的方法–類方法( 而不是的實(shí)例方法)。類對(duì)象從父類那里繼承類方法是越,就像實(shí)例從父類那里繼承實(shí)例方法一樣耳舅。③類對(duì)象與類名在源代碼中,類對(duì)象由類名表示倚评。在下面的例子中浦徊,Retangle類 用從NSObject那里繼承來(lái)的方法來(lái)返回類的版本號(hào):int versionNumber = [Rectangle version];只有在消息表達(dá)式中作為接收者,類名才代表類對(duì)象天梧。其他地方盔性,你需要要求一個(gè)實(shí)例或者類返回class id。 響應(yīng)class消息:id aClass = [anObject class];id rectClass = [Rectangle class];如同上面的例子顯示的那樣腿倚,類對(duì)象像其他對(duì)象一樣纯出,也是id類型蚯妇。
總之,類對(duì)象是一個(gè)功能完整的對(duì)象暂筝,所以也能被動(dòng)態(tài)識(shí)別(dynamically typed)箩言,接收消息,從其他類繼承方法焕襟。特殊之處在于它們是由編譯器創(chuàng)建的陨收,缺少它們自己的數(shù)據(jù)結(jié)構(gòu)(實(shí)例變量),只是在運(yùn)行時(shí)產(chǎn)生實(shí)例的代理鸵赖。
3务漩、元類對(duì)象(metaclass object)①元類對(duì)象的實(shí)質(zhì)實(shí)際上,類對(duì)象是元類對(duì)象的一個(gè)實(shí)例K省饵骨!元類描述了 一個(gè)類對(duì)象,就像類對(duì)象描述了普通對(duì)象一樣茫打。不同的是元類的方法列表是類方法的集合居触,由類對(duì)象的選擇器來(lái)響應(yīng)。當(dāng)向一個(gè)類發(fā)送消息時(shí)老赤,objc_msgSend會(huì)通過(guò)類對(duì)象的isa指針定位到元類轮洋,并檢查元類的方法列表(包括父類)來(lái)決定調(diào)用哪個(gè)方法。元類代替了類對(duì)象描述了類方法抬旺,就像類對(duì)象代替了實(shí)例對(duì)象描述了實(shí)例化方法弊予。很顯然,元類也是對(duì)象开财,也應(yīng)該是其他類的實(shí)例汉柒,實(shí)際上元類是根元類(root class’s metaclass)的實(shí)例,而根元類是其自身的實(shí)例,即根元類的isa指針指向自身床未。類的super_class指向其父類竭翠,而元類的super_class則指向父類的元類振坚。元類的super class鏈與類的super class鏈平行薇搁,所以類方法的繼承與實(shí)例方法的繼承也是并行的。而根元類(root class’s metaclass)的super_class指向根類(root class)渡八,這樣啃洋,整個(gè)指針鏈就鏈接起來(lái)了!屎鳍!
記住宏娄,當(dāng)一個(gè)消息發(fā)送給任何一個(gè)對(duì)象, 方法的檢查 從對(duì)象的 isa 指針開(kāi)始逮壁,然后是父類孵坚。實(shí)例方法在類中定義, 類方法 在元類和根類中定義。(根類的元類就是根類自己)卖宠。在一些計(jì)算機(jī)語(yǔ)言的原理中巍杈,一個(gè)類和元類層次結(jié)構(gòu)可以更自由的組成,更深元類鏈和從單一的元類繼承的更多的實(shí)例化的類扛伍。Objective-C 的類方法 是使用元類的根本原因筷畦,在其他方面試圖在隱藏元類。例如 [NSObject class] 完全相等于 [NSObject self]刺洒,所以鳖宾,在形式上他還是返回的 NSObject->isa 指向的元類。 Objective-C語(yǔ)言是一組實(shí)用的折中方案逆航。
還有些不明白鼎文? 下面這個(gè)圖標(biāo)可能會(huì)有些幫助:

綜上所述,類對(duì)象(class object)中包含了類的實(shí)例變量因俐,實(shí)例方法的定義漂问,而元類對(duì)象(metaclass object)中包括了類的類方法(也就是C++中的靜態(tài)方法)的定義。類對(duì)象和元類對(duì)象中當(dāng)然還會(huì)包含一些其它的東西女揭,蘋果以后也可能添加其它的內(nèi)容蚤假,但對(duì)于我們只需要記住:類對(duì)象存的是關(guān)于實(shí)例對(duì)象的信息(變量吧兔,實(shí)例方法等)磷仰,而元類對(duì)象(metaclass object)中存儲(chǔ)的是關(guān)于類的信息(類的版本,名字境蔼,類方法等)灶平。要注意的是,類對(duì)象(class object)和元類對(duì)象(metaclass object)的定義都是objc_class結(jié)構(gòu)箍土,其不同僅僅是在用途上逢享,比如其中的方法列表在類對(duì)象(instance object)中保存的是實(shí)例方法(instance method),而在元類對(duì)象(metaclass object)中則保存的是類方法(class method)吴藻。關(guān)于元類對(duì)象可以參考蘋果官方文檔" The Objective-‐C Programming Language "
4瞒爬、類對(duì)象和元類對(duì)象的相關(guān)方法
①object_getClass跟隨實(shí)例的isa指針,返回此實(shí)例所屬的類沟堡,對(duì)于實(shí)例對(duì)象(instance)返回的是類(class),對(duì)于類(class)則返回的是元類(metaclass),②-class方法對(duì)于實(shí)例對(duì)象(instance)會(huì)返回類(class),但對(duì)于類(class)則不會(huì)返回元類(metaclass),而只會(huì)返回類本身侧但,即[@"instance" class]返回的是__NSCFConstantString,而[NSString class]返回的是NSString。③class_isMetaClass可判斷某類是否為元類.
④使用objc_allocateClassPair可在運(yùn)行時(shí)創(chuàng)建新的類與元類對(duì)航罗,使用class_addMethod和class_addIvar可向類中增加方法和實(shí)例變量禀横,最后使用objc_registerClassPair注冊(cè)后,就可以使用此類了粥血“爻看到動(dòng)態(tài)語(yǔ)言牛逼的地方了嗎酿箭,可以在需要時(shí)更改已經(jīng)定義好的類!Objective-C的類別方法估計(jì)底層就是這么實(shí)現(xiàn)的趾娃,只是不知道為什么類別不能增加實(shí)例變量七问,有高手請(qǐng)留言。
----by wangzz

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末茫舶,一起剝皮案震驚了整個(gè)濱河市械巡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饶氏,老刑警劉巖讥耗,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異疹启,居然都是意外死亡古程,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門喊崖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)挣磨,“玉大人,你說(shuō)我怎么就攤上這事荤懂∽氯梗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵节仿,是天一觀的道長(zhǎng)晤锥。 經(jīng)常有香客問(wèn)我,道長(zhǎng)廊宪,這世上最難降的妖魔是什么矾瘾? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮箭启,結(jié)果婚禮上壕翩,老公的妹妹穿的比我還像新娘。我一直安慰自己傅寡,他們只是感情好放妈,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著赏僧,像睡著了一般大猛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上淀零,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音膛壹,去河邊找鬼驾中。 笑死唉堪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肩民。 我是一名探鬼主播唠亚,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼持痰!你這毒婦竟也來(lái)了灶搜?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤工窍,失蹤者是張志新(化名)和其女友劉穎割卖,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體患雏,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鹏溯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了淹仑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丙挽。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖匀借,靈堂內(nèi)的尸體忽然破棺而出颜阐,到底是詐尸還是另有隱情,我是刑警寧澤吓肋,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布瞬浓,位于F島的核電站,受9級(jí)特大地震影響蓬坡,放射性物質(zhì)發(fā)生泄漏猿棉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一屑咳、第九天 我趴在偏房一處隱蔽的房頂上張望萨赁。 院中可真熱鬧,春花似錦兆龙、人聲如沸杖爽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)慰安。三九已至,卻和暖如春聪铺,著一層夾襖步出監(jiān)牢的瞬間化焕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工铃剔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撒桨,地道東北人查刻。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凤类,于是被迫代替她去往敵國(guó)和親穗泵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容