Objective-C中的meta-class

來源:互聯網
上載者:User

討論Objective-C的一個奇怪的概念 meta-class

在Objective-C中的每個類,都有它自己相關的meta-class,但因為你很少直接使用meta-class,所以顯得很神秘。

在運行時建立一個類

下面的代碼在運行時建立一個NSError新的子類,並添加一個方法到裡面:

 
Class newClass =
    objc_allocateClassPair([NSError class], “RuntimeErrorSubclass”, 0);
class_addMethod(newClass, @selector(report), (IMP)ReportFunction, “v@:”);
objc_registerClassPair(newClass);

添加的這個方法用ReportFunction函數名作為它的實現,實現定義在下面

 

void ReportFunction(id self, SEL _cmd)
{
    NSLog(@”This object is %p.”, self);
    NSLog(@”Class is %@, and super is %@.”, [self class], [self superclass]);
 
    Class currentClass = [self class];
    for (int i = 1; i < 5; i++)
    {
        NSLog(@”Following the isa pointer %d times gives %p”, i, currentClass);
        currentClass = object_getClass(currentClass);
    }
 
    NSLog(@”NSObject’s class is %p”, [NSObject class]);
    NSLog(@”NSObject’s meta class is %p”, object_getClass([NSObject class]));
}

表面上,這都很簡單。在運行時建立一個新類,只需要3步

1)為 class pair分配儲存空間 (使用objc_allocateClassPair)

2)增加需要的方法和ivars(使用class_addMethod來添加方法)

3) 註冊這個類,以便它能被別人使用(objc_registerClassPair)

 

現在的問題是,什麼是class pair, 函數objc_allocateClassPair只返回一個值:the class

那麼pair的另外一半在哪裡呢?你可能已經猜到另外一般就是meta-class(也就是本文的主題)

一個資料結構需要哪些東西才能成為一個對象

每個對象都有一個類,這是一個基本的物件導向的概念。

在Objective-C中,任何資料結構,如果在正確的位置有一個指向類的指標,就能被視為一個對象。

在Objective-C中,一個對象的類,由它的isa指標決定。這個isa指標指向 對象的類。

事實上,一個對象的基本定義是這樣的:

 

typedef struct objc_object {

    Class isa;

} *id;

 

這就是說,任何以一個指向Class結構的指標開始的結構,都能被當作objc_object

對象最重要的特性,就是你可以給它們發送訊息:

 

[@"stringValue"

    writeToFile:@"/file.txt" atomically:YES encoding:NSUTF8StringEncoding error:NULL];

 

 

當你發送訊息給一個Objective-C對象時(比如這裡的NSCFString), 運行時(runtime) 通過對象的isa指標得到對象的Class(這裡是NSCFString類),而Class裡含有那些可以應用這個類的所有對象上的所有方法的列表,以及指向superclass的指標。運行時通過類的方法列表和超類,來發現一個能同訊息選擇子匹配的方法(上面的例子中,就是在NSString類中的writeToFile:atomically:encoding:error方法)。

要點就是:類定義了那些訊息,你只能發送那些已經定義好的訊息給它的對象

 

什麼是meta-class

現在,你可能已經知道,在Objective-C中,一個類也是一個對象。這意味著,你也可以發送訊息給一個類

NSStringEncoding defaultStringEncoding = [NSString defaultStringEncoding];

在這種情況下, defaultStringEncoding被發送給NSString類

在Objective-C 中,每個類,都是一個對象。也就是說,類結構也必須以isa指標開始,這樣,它才同objc_object結構二進位相容

在結構裡的第2個項目,必須是superclass的指標(如果是基類,沒有父類的話,設定為nil)

 

定義一個類,有很多不同的方式,依賴於你的運行時版本而不同,但他們都以 isa開始,然後後面接著superclass

 

typedef struct objc_class *Class;

struct objc_class {

    Class isa;

    Class super_class;

    /* followed by runtime specific details… */

};

為了讓我們調用類的一個方法,類的isa指標必須指向一個類結構,並且,類結構必須含有我們能在該類上調用的方法列表

這就導致了一個meta-class的定義:meta-class是一個類對象的類

簡單地說,

當你發送一條訊息給一個對象時,這條訊息會在對象的類的方法列表裡尋找

當你發送一條訊息給一個類時,就會在類的meta-class的方法列表理尋找訊息

meta-class是必不可少的,因為它儲存了一個類的類 方法。每個類都必須只有唯一的meta-class,因為每個類都只可能有一個唯一的類方法列表。

 

 

meta-class的類又是什麼呢?

meta-class,跟 類一樣,它也是一個對象。這意味著,你也可以在它上面調用方法。自然地,這意味這,它也必須有一個類。

所有的meta-class都使用基類的meta-class(在它們的繼承體系中,最頂層的類的meta-class)作為它們自己的類。這意味著,所有從NSObject繼承來的類,它們的meta-class都將NSObject的meta-class作為自己的類

遵循這個規則,所有的meta-class使用基類的meta-class作為它們自己的類,任何base meta-class都將是它自己的類(它們的isa指標指向它們自己)。也就是說,在 NSObject的meta-class的isa指標將指向它自己(它是自己的一個執行個體)

 

類和 meta-class的繼承

同樣的方式,類用super_class 指標指向超類,meta-class使用它自己的super_class指向 類的super-class的meta-class

巧合地是,基類的meta-class設定它的 super_class 為基類自己。

http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html

http://www.sealiesoftware.com/blog/class%20diagram.pdf

 

用實驗來驗證我們的想法

為了確認這些情況,我們看看ReportFunctional的輸出。 這個函數的目的是 追蹤isa指標,並記錄在哪裡找到的它。

為了運行ReportFunction,我們需要建立這個動態建立的類的執行個體,然後調用它的report方法

 

id instanceOfNewClass =

    [[newClass alloc] initWithDomain:@”someDomain” code:0 userInfo:nil];

[instanceOfNewClass performSelector:@selector(report)];

[instanceOfNewClass release];

因為沒有report方法的聲明,我使用performSelector:來調用它,所以編譯不會給出什麼警告

 

ReportFunction將遍曆isa指標,告訴我們那些對象被當成類,meta-class,以及meta-class的類 來使用

 

取得一個對象的類:ReportFunction將使用object_getClass來追蹤isa指標, 因為isa指標是類的一個被保護的成員(你不能直接存取其他類的isa指標)

ReportFunction不使用類方法來實現這個,因為調用一個類對象的類方法,將不會返回meta-class. 而是再次返回這個類(所以[NSString class]將返回NSString類,而不是NSString的meta-class)

 

 

結論:

meta-class是類對象的類。每個類都有它自己唯一的meta-class(因為每個類都有它自己唯一的方法列表)

http://cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.