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ì)有些幫助:
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