现在的位置: 首页 > 综合 > 正文

An introduction to Objective-C Meta Class

2012年12月08日 ⁄ 综合 ⁄ 共 3501字 ⁄ 字号 评论关闭
An introduction to Objective-C Meta Class
First, let's have a look at the base class NSObject.
@interface NSObject <NSObject> {    //implement protocol NSObject
    Class    isa;    //point to meta class, all instances of NSObject share the same meta class.
}
+ (void)load;
+ (void)initialize;
- (id)init;

+ (id)new;
+ (id)allocWithZone:(NSZone *)zone;
+ (id)alloc;
- (void)dealloc;

+ (Class)superclass;
+ (Class)class;
...

@end

Class is defined as:
typedef struct objc_class *Class;
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;
objc_class is the meta class.

id is defined as:
typedef struct objc_object {
    Class isa;
} *id;
id is an pointer pointed to struct obj_object very similar with the definition of NSObject.

//class TestA
@interface TestA : NSObject {
   
    int a;

}

+ (id)alloc;
+ (void)initialize;

@end

@implementation TestA

+ (void)load
{
    printf("load TestA. %s %#x\n", [[self description] UTF8String], self);
}

+ (id)alloc
{
    self = [super alloc];
    printf("alloc TestA. %s %#x\n", [[self description] UTF8String], self);
    return self;
}

+ (void)initialize
{
    printf("initialize TestA. %s %#x\n", [[self description] UTF8String], self);
}

- (id)init
{
    self = [super init];
    if(self)
    {
        printf("init TestA. %s %#x isa=%#x\n", [[self description] UTF8String], self, isa);
    }
    return self;
}

@end

//End of TestA

//class TestB
@interface TestB : TestA {

    int b;
   
}

+ (id)alloc;

+ (void)initialize;

@end

@implementation TestB

+ (void)load
{
    printf("load TestB. %s %#x\n", [[self description] UTF8String], self);
}

+ (id)alloc
{
    self = [super alloc];
    printf("alloc TestB. %s %#x\n", [[self description] UTF8String], self);
    return self;
}

+ (void)initialize
{
    printf("initialize TestB. %s %#x\n", [[self description] UTF8String], self);
}

- (id)init
{
    self = [super init];
    if(self)
    {
        printf("init TestB. %s %#x isa=%#x\n", [[self description] UTF8String], self, isa);
    }
    return self;
}
@end
//End of TestB

//Testing example
TestB *b1 = [[TestB alloc] init];
TestB *b2 = [[TestB alloc] init];
TestA *a1 = [[TestA alloc] init];

Output:
initialize TestA. TestA 0xd634
load TestA. TestA 0xd634
initialize TestB. TestB 0xd65c
load TestB. TestB 0xd65c
alloc TestA. <TestB: 0x4e317f0> 0x4e317f0
alloc TestB. <TestB: 0x4e317f0> 0x4e317f0
init TestA. <TestB: 0x4e317f0> 0x4e317f0 isa=0xd65c
init TestB. <TestB: 0x4e317f0> 0x4e317f0 isa=0xd65c
alloc TestA. <TestB: 0x4e369e0> 0x4e369e0
alloc TestB. <TestB: 0x4e369e0> 0x4e369e0
init TestA. <TestB: 0x4e369e0> 0x4e369e0 isa=0xd65c
init TestB. <TestB: 0x4e369e0> 0x4e369e0 isa=0xd65c
alloc TestA. <TestA: 0x4e34930> 0x4e34930
init TestA. <TestA: 0x4e34930> 0x4e34930 isa=0xd634

From the outputs, some rules can be concluded:
1. In class method, such as initialize, load, alloc. self is the address of meta class, in another word, a pointer to struct objc_class.
2. The first time a class is referenced, its meta class will only be initialized and loaded once.
3. All instances of class objects share a meta class.
4. TestB inherits from TestA. The meta class address of TestB is 0xd65c. The meta class address of TestA is 0xd634. So TestB.isa->super_class = 0xd634. so TestB can call super's methods. All methods and meta infomations are stored in isa.

抱歉!评论已关闭.