问题
I want to know how the language's object-oriented features are implemented in C.
As defined in <objc/runtime.h>, id type is a pointer to a objc_object, and objc_object type is a C-structure with only one member isa storing a Class. Then where and how are the actual values of any object's instance-variables stored?
One more thing, the fact that all objective-C object-pointers can be casted to id (which is a pointer to a C-structure, where no feature such as inheritance exists), are Objective-C classes just qualifiers for the compiler, and all instances equally type of objc_object?
added:
NSObject *obj = [NSObject new];
objc_object *objStruct = (__bridge objc_object *)obj;
NSLog(@"obj: %@", NSStringFromClass(objStruct->isa));
NSString *str = [NSString new];
objc_object *strStruct = (__bridge objc_object *)str;
NSLog(@"str: %@", NSStringFromClass(strStruct->isa));
This code compiles and outputs:
obj: NSObject, str: __NSCFConstantString
Both obj and str can be casted to objc_object *, which means both variables are pointers of a same type, no?
resolved
Understood! I was misunderstanding how pointer-casting works. obj and str are pointers of different structure-types, but both commonly have Class-type member isa at the front of the memory, so can be treated as a objc_object. The code below mimics this mechanism:
typedef struct {
int isa;
} Fake_NSObject;
typedef struct {
int isa;
char *string;
} Fake_NSString;
Fake_NSObject obj = {1};
Fake_NSObject *objPtr = &obj;
NSLog(@"obj: %d", objPtr->isa); // prints 1
Fake_NSString str = {2, "abc"};
Fake_NSString *strPtr = &str;
NSLog(@"str: %d", strPtr->isa); // prints 2
Fake_NSObject *objPtr2 = (Fake_NSObject *)strPtr; // this is ok.
NSLog(@"obj2: %d", objPtr2->isa); // prints 2
Fake_NSString *strPtr2 = (Fake_NSString *)objPtr; // this is invalid, but still works.
NSLog(@"str2: %d", strPtr2->isa); // prints 1
Thanks!
回答1:
Then where and how are the actual values of it's instance-variables stored?
They're stored in the same place as always -- inside the object. As you say, id represents a pointer to any kind of object. However, it doesn't define any specific type beyond that -- it doesn't say anything about the actual type of the object.
objc_object is just a base type that's equivalent to NSObject. Take a look at NSObject.h and you'll see that an instance of NSObject has a single instance variable, the isa pointer. The same is true for NSProxy, which is another root class in Objective-C. Subclasses of NSObject or NSProxy can add their own instance variables, which are appended to the parent's structure.
if all objective-C object-pointers can be casted to id, are all Objective-C classes just qualifiers for the compiler, and at runtime all those instances equally type of objc_object?
I'm not sure what you're asking here. The compiler won't stop you from sending any message to any object (although it will warn you if it thinks you're sending a message to an object that doesn't support it), so in a sense the compiler doesn't care about the various object types. On the other hand, objects of different types are different -- there's not universal type that all classes are converted to.
id is strongly analogous to void *. void * is a generic pointer, and you can cast any pointer to void *, but that doesn't mean that all pointers are equivalent. id is pretty much the same thing with the added restriction that the pointer you assign to a variable of type id has to point to an Objective-C object.
来源:https://stackoverflow.com/questions/16783557/are-objective-c-objects-all-same-type-of-c-structure