Objective C物件之類物件和元類物件

2021-07-09 02:59:22 字數 3946 閱讀 4144

作為c語言的超集,物件導向成為objective-c與c語言的最大區別,因此,物件是objective-c中最重要的部分之一。目前物件導向的語言有很多,objective-c中的物件又和其他語言中的物件有什麼區別呢?下面來簡單介紹objective-c中物件的實現。

1、objective-c中的類

誰都知道,所有的物件都是由其對應的類例項化而來,殊不知

類本身也是一種物件,先不要對這句話感到驚訝。

首先我們來關注objective-c中的類。在objective-c中,我們用到的幾乎所有類都是nsobject類的子類,nsobject類定義格式如下(忽略其方法宣告):

@inte***ce nsobject

這個class為何物?在objc.h中我們發現其僅僅是乙個結構(struct)指標的typedef定義:

typedef struct objc_class *class;

同樣的,objc_class又是什麼呢?在objective-c2.0中,objc_class的定義如下:

struct objc_class

寫到這裡大家可能就暈了,怎麼又有乙個isa??這些isa到底是什麼?之間有什麼區別和聯絡?接下來解答這一連串的疑問。

其實在objective-c中任何的類定義都是物件。即在程式啟動的時候任何類定義都對應於一塊記憶體。在編譯的時候,編譯器會給每乙個類生成乙個且只生成乙個」描述其定義的物件」,也就是蘋果公司說的類物件(class object),他是乙個單例(singleton), 而我們在c++等語言中所謂的物件,叫做例項物件(instance object)。對於例項物件我們不難理解,但類物件(class object)是幹什麼吃的呢?我們知道objective-c是門很動態的語言,因此程式裡的所有例項物件(instace object)都是在執行時由objective-c的執行時庫生成的,而這個類物件(class object)就是執行時庫用來建立例項物件(instance object)的依據。

再回到之前的問題,腫麼這個例項物件(instance object)的isa指標指向的類物件(class object)裡面還有乙個isa呢?這個類物件(class objec)的isa指向的依然是乙個objc-class,它就是「元類物件」(metaclass object),它和類物件(class object)的關係是這樣的:

2、類物件(class object)

①類物件的實質

我們知道了:類物件是由編譯器建立的,即在編譯時所謂的類,就是指類物件(官方文件中是這樣說的: the class object is the compiled version of the class)。任何直接或間接繼承了nsobject的類,它的例項物件(instance objec)中都有乙個isa指標,指向它的類物件(class object)。這個類物件(class object)中儲存了關於這個例項物件(instace object)所屬的類的定義的一切:包括變數,方法,遵守的協議等等。因此,類物件能訪問所有關於這個類的資訊,利用這些資訊可以產生乙個新的例項,但是類物件不能訪問任何例項物件的內容。

當你呼叫乙個 「類方法」 例如 [nsobject alloc],你事實上是傳送了乙個訊息給他的類物件。

②類物件和例項物件的區別

當然有區別了,儘管類物件保留了乙個類例項的原型,但它並不是例項本身。它沒有自己的例項變數,也不能執行那些類的例項的方法(只有例項物件才可以執行例項方法)。然而,類的定義能包含那些特意為類物件準備的方法–類方法( 而不是的例項方法)。類物件從父類那裡繼承類方法,就像例項從父類那裡繼承例項方法一樣。

③類物件與類名

在源**中,類物件由類名表示。

在下面的例子中,retangle類 用從nsobject那裡繼承來的方法來返回類的版本號:

int versionnumber = [rectangle version];

只有在訊息表示式中作為接收者,類名才代表類物件。其他地方,你需要要求乙個例項或者類返回class id。 響應class訊息:

id aclass = [anobject class];

id rectclass = [rectangle class];

如同上面的例子顯示的那樣,類物件像其他物件一樣,也是id型別。

總之,類物件是乙個功能完整的物件,所以也能被動態識別(dynamically typed),接收訊息,從其他類繼承方法。特殊之處在於它們是由編譯器建立的,缺少它們自己的資料結構(例項變數),只是在執行時產生例項的**。

3、元類物件(metaclass object)

①元類物件的實質

實際上,類物件是元類物件的乙個例項!!元類描述了 乙個類物件,就像類物件描述了普通物件一樣。不同的是元類的方法列表是類方法的集合,由類物件的選擇器來響應。當向乙個類傳送訊息時,objc_msgsend會通過類物件的isa指標定位到元類,並檢查元類的方法列表(包括父類)來決定呼叫哪個方法。元類代替了類物件描述了類方法,就像類物件代替了例項物件描述了例項化方法。

很顯然,元類也是物件,也應該是其他類的例項,實際上元類是根元類(root class』s metaclass)的例項,而根元類是其自身的例項,即根元類的isa指標指向自身。

類的super_class指向其父類,而元類的super_class則指向父類的元類。元類的super class鏈與類的super class鏈平行,所以類方法的繼承與例項方法的繼承也是並行的。而根元類(root class』s metaclass)的super_class指向根類(root class),這樣,整個指標鏈就鏈結起來了!!

記住,當乙個訊息傳送給任何乙個物件, 方法的檢查 從物件的 isa 指標開始,然後是父類。例項方法在類中定義, 類方法 在元類和根類中定義。(根類的元類就是根類自己)。在一些計算機語言的原理中,乙個類和元類層次結構可以更自由的組成,更深元類鏈和從單一的元類繼承的更多的例項化的類。objective-c 的類方法 是使用元類的根本原因,在其他方面試圖在隱藏元類。例如 [nsobject class] 完全相等於 [nsobject self],所以,在形式上他還是返回的 nsobject->isa 指向的元類。 objective-c語言是一組實用的折中方案。

還有些不明白? 下面這個圖示可能會有些幫助:

綜上所述,類物件(class object)中包含了類的例項變數,例項方法的定義,而元類物件(metaclass object)中包括了類的類方法(也就是c++中的靜態方法)的定義。類物件和元類物件中當然還會包含一些其它的東西,蘋果以後也可能新增其它的內容,但對於我們只需要記住:類物件存的是關於例項物件的資訊(變數,例項方法等),而元類物件(metaclass object)中儲存的是關於類的資訊(類的版本,名字,類方法等)。要注意的是,類物件(class object)和元類物件(metaclass object)的定義都是objc_class結構,其不同僅僅是在用途上,比如其中的方法列表在類物件(instance object)中儲存的是例項方法(instance method),而在元類物件(metaclass object)中則儲存的是類方法(class method)。關於元類物件可以參考蘋果官方文件" the objective-‐c programming language "

4、類物件和元類物件的相關方法

①object_getclass跟隨例項的isa指標,返回此例項所屬的類,對於例項物件(instance)返回的是類(class),對於類(class)則返回的是元類(metaclass),

②-class方法對於例項物件(instance)會返回類(class),但對於類(class)則不會返回元類(metaclass),而只會返回類本身,即[@"instance" class]返回的是__nscfconstantstring,而[nsstring class]返回的是nsstring。

③class_ismetaclass可判斷某類是否為元類.                                     

----by wangzz

Objective C之類和物件

面向過程程式設計 procedure oriented programming,pop 以事件為中心,關心完成該事件的詳細步驟,一步一步如何實現.物件導向程式設計 object oriented programming,oop 以事物為中心,也就是引數事件的參與者,設計事物的功能,而完成事件只是事物...

Objective C語法之類和物件

下圖中是一段的類宣告的語法展示,宣告了乙個叫做 myclass 的類,它繼承於根類 nsobject。根類可以被所有的其他類直接或間接繼承。下圖是乙個方法的語法展示,方法的宣告由以下幾個部分構成 方法型別識別符號,返回型別,乙個或多個方法簽名關鍵字,以及引數型別和名稱。類的實體變數的訪問許可權 對應...

Objective C語法之類和物件

下圖中是一段的類宣告的語法展示,宣告了乙個叫做 myclass 的類,它繼承於根類 nsobject。根類可以被所有的其他類直接或間接繼承。下圖是乙個方法的語法展示,方法的宣告由以下幾個部分構成 方法型別識別符號,返回型別,乙個或多個方法簽名關鍵字,以及引數型別和名稱。1.2 生成student.h...