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:
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:
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;
}
+ (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: 0x4e0000e0> 0x4e0000e0
Alloc testb. <testb: 0x4e0000e0> 0x4e0000e0
Init Testa. <testb: 0x4e0000e0> 0x4e0000e0 ISA = 0xd65c
Init testb. <testb: 0x4e0000e0> 0x4e0000e0 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.