Discussing a strange concept of objective-C: meta-class
Every class in objective-C has its own meta-class, but it is mysterious because you seldom use meta-class directly.
Create a class at runtime
The following code creates a new nserror subclass at runtime and adds a method to it:
Class newclass =
Objc_allocateclasspair ([nserror class], "runtimeerrorsubclass", 0 );
Class_addmethod (newclass, @ selector (report), (IMP) reportfunction, "V @:");
Objc_registerclasspair (newclass );
The added method uses the reportfunction name as its implementation. The implementation is defined below
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]);
}
On the surface, this is very simple. Create a new class at runtime, only three steps are required
1) Allocate storage space for class pair (use objc_allocateclasspair)
2) Add required methods and ivars (use class_addmethod to add methods)
3) register this class so that it can be used by others (objc_registerclasspair)
The problem is: what is the class pair? The objc_allocateclasspair function returns only one value: the class
So where is the other half of pair? You may have guessed that the other is meta-class (the topic of this Article)
What does a data structure need to become an object?
Each object has a class, which is a basic object-oriented concept.
In objective-C, any data structure, if there is a pointer to the class at the correct position, can be considered as an object.
In objective-C, the class of an object is determined by its ISA pointer. This isa Pointer Points to the class of the object.
In fact, the basic definition of an object is as follows:
Typedef struct objc_object {
Class ISA;
} * ID;
This means that any structure starting with a pointer pointing to the class structure can be treated as objc_object
The most important feature of objects is that you can send messages to them:
[@ "Stringvalue"
Writetofile: @ "/file.txt" atomically: Yes encoding: nsutf8stringencoding error: NULL];
When you send a message to an objective-C object (such as nscfstring), the runtime obtains the class of the object through the ISA pointer of the object (this is the nscfstring class ), the class contains a list of all methods on all objects that can apply this class, And a pointer to superclass. The method list and superclass of the class are used to find a method that can be matched with the message selection (in the above example, the writetofile: atomically: encoding: error Method ).
The main point is: the class defines those messages. You can only send the defined messages to the objects.
What is meta-class?
Now, you may already know that in objective-C, a class is also an object. This means that you can also send messages to a class
Nsstringencoding defaultstringencoding = [nsstring defaultstringencoding];
In this case, defaultstringencoding is sent to the nsstring class
In objective-C, each class is an object. That is to say, the class structure must also start with the ISA pointer so that it is Binary compatible with the objc_object structure.
The 2nd items in the structure must be superclass pointers (if the base class does not have a parent class, set it to nil)
There are many different ways to define a class, depending on your runtime version, but they all start with ISA, and then follow the superclass
Typedef struct objc_class * class;
Struct objc_class {
Class ISA;
Class super_class;
/* Followed by runtime specific details... */
};
In order for us to call a class method, the ISA pointer of the class must point to a class structure, and the class structure must contain a list of methods that can be called on the class.
This leads to the definition of a meta-class: meta-class is the class of A Class Object.
Simply put,
When you send a message to an object, the message will be searched in the method list of the object class.
When you send a message to a class, you will find the message in the meta-class method list of the class.
Meta-class is essential because it stores the class methods of a class. Each class must have a unique meta-class, because each class may only have a unique list of class methods.
What is the meta-class?
Meta-class, like a class, is also an object. This means that you can also call methods on it. Naturally, this means that it must also have a class.
All meta-classes use the meta-class of the base class (in their inheritance system, the meta-class of the top-level class) as their own classes. This means that all classes inherited from nsobject have nsobject meta-class as their own class.
Following this rule, all meta-classes use the meta-class of the base class as their own classes, any base meta-class will be its own class (their Isa Pointer Points to their own ). That is to say, the ISA pointer of meta-class in nsobject points to itself (it is an instance of its own)
Class and meta-class inheritance
In the same way, the class uses the super_class pointer to point to the superclass, And the meta-class uses its own super_class to point to the meta-class of the super-class of the class.
Coincidentally, the meta-class of the base class sets its super_class as the base class itself.
Http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
Http://www.sealiesoftware.com/blog/class%20diagram.pdf
Use experiments to verify our ideas
To confirm these situations, let's look at the output of reportfunctional. The purpose of this function is to track the ISA pointer and record where it is found.
To run reportfunction, we need to create an instance of the dynamically created class and call its report method.
Id instanceofnewclass =
[[Newclass alloc] initwithdomain: @ "somedomain" code: 0 userinfo: Nil];
[Instanceofnewclass extends mselector: @ selector (report)];
[Instanceofnewclass release];
Because there is no declaration of the report method, I use javasmselector: to call it, So compilation will not give any warning
Reportfunction traverses the ISA pointer and tells us that objects are used as classes, meta-class, and meta-class classes.
Get an object class: reportfunction will use object_getclass to track the ISA pointer, because the ISA pointer is a protected member of the class (you cannot directly access the ISA pointer of other classes)
Reportfunction does not use class methods to implement this. Because the class method of A Class Object is called, meta-class is not returned. instead, this class is returned again (so [nsstring class] will return the nsstring class instead of the nsstring meta-class)
Conclusion:
Meta-class is the class of class objects. Each class has its own unique meta-class (because each class has its own unique list of methods)
Http://cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html