2012-06-29 64 views
2

從 「objc.h」:在Cocoa中,Class類是如何定義的?

typedef struct objc_class *Class; 

但在 「runtime.h」:

struct objc_class { 
    Class isa; 

#if !__OBJC2__ 
    Class super_class          OBJC2_UNAVAILABLE; 
    const char *name           OBJC2_UNAVAILABLE; 
    long version            OBJC2_UNAVAILABLE; 
    long info            OBJC2_UNAVAILABLE; 
    long instance_size          OBJC2_UNAVAILABLE; 
    struct objc_ivar_list *ivars        OBJC2_UNAVAILABLE; 
    struct objc_method_list **methodLists     OBJC2_UNAVAILABLE; 
    struct objc_cache *cache         OBJC2_UNAVAILABLE; 
    struct objc_protocol_list *protocols      OBJC2_UNAVAILABLE; 
#endif 

} OBJC2_UNAVAILABLE; 
/* Use `Class` instead of `struct objc_class *` */ 

到底是什麼Class

+0

'typedef'表明它是一個指向'struct objc_class'的指針,不是? – dasblinkenlight

+0

@dasblinkenlight他可能對'Class'成爲'struct objc_class'成員感到困惑。 – trojanfoe

+0

是的,我很困惑 - 請你能向我解釋它到底是什麼嗎?因爲我認爲這是兩個標題之間的循環引用。 –

回答

10
typedef struct objc_class *Class; 

^這是objc_class指針的前向聲明。它給了它不錯的友好名稱Class

現在讓我們來看看objc_class結構: (刪除的Objective-C 2.0檢查,以縮短它)

struct objc_class { 
    Class isa; 
}; 
//This is really saying 
struct objc_class { 
    struct objc_class *isa; 
}; 

所以現在我們有一個指向它自己的類型結構。但你爲什麼要問?

Inside the Objective-C Runtime, Part 2

的Class由類ISA(類級)包含在其objc_method_list的 類類的方法指向兩者。瞭解?在運行時使用的術語是,儘管對象的isa指向其Class的 ,但Class的isa指向對象的「meta Class」。

那麼元類'isa指針呢?那麼,這指向層次結構的根 類(大多數情況下爲NSObject)。 (在基金會 框架中NSObject的一個子類的每個元類「isa」爲 NSObject的實例)。是的,順便說一句,NSObject的元類'isa指向 到同一個結構 - 它是一個循環引用,所以沒有類'isa是 曾經是NULL。


所以根據這樣的描述,當你創建一個類從NSObject繼承你有一個isa指向指向指向它的根類(NSObject)它的元類的類類型包含一個循環引用本身。這就解釋了它之所以爲requires two steps to determine if an object is an instance or a class

比方說,你創建了以下類:

@interface MyClass : NSObject 
@end 
@implementation MyClass 
@end 


如果能夠*遍歷isa指針,你會得到如下:
* 你不能因爲isa受到保護。請參閱下面的Cocoa with Love文章以創建您自己的實現。

Class c = myClassInstance->isa; //This would be the MyClass 
c = c->isa; //This would be MyClass' meta class 
c = c->isa; //This would be NSObjects meta class 
c = c->isa; //This going forward would still be the NSObjects meta class 
... 

一旦c == c->isa你會知道你是在根對象。請記住,Objective-C是C的一個超集,它本身並不具有面向對象的結構,如繼承。這與其他實現細節(如構成完整類層次結構的超類的指針)一起允許Objective-C提供面向對象的功能。有關類和元類的更多信息請參見第可可後用愛:What is a meta-class in Objective-C?

+0

不錯的答案,但一件小事...如果OP的代碼是正確的,那麼「移除Objective-C 2.0檢查以縮短它」將移除* whole *定義 - 注意'struct'本身的最終'OBJC2_UNAVAILABLE'。 – CRD

+1

是的,它的確如此,你根本不應該使用'objc_class'結構。每個類都有一個'isa'作爲它的第一個成員仍然是強制性的,所以我只是爲示例添加了一個簡短版本的結構。其餘細節都是在'OBJC2'中定義的。 – Joe

+0

好的答案!非常感謝。 –

0

大約圓形參考:

如果如以下ISA定義不是一個指針,那麼這成爲一個循環引用。

struct objc_class { 
    struct objc_class isa; 
}; 

因爲編譯器無法計算objc_class的大小。

但是,在以下情況下(真正的定義),

struct objc_class { 
    struct objc_class *isa; 
}; 

ISA只是一個指針,所以沒有這個問題。

相關問題