id类型是什么:
可见id是一个指向objc_object结构体的指针。
看一条语句就清晰了:
id obj = [[NSObject alloc] init];
所以对象obj就是一个objc_object结构体。它们都有个成员变量isa,其类型为objc_class。它又是一个指针,指向objc_class结构体,那么下面再看objc_class里面有什么。
objc_class是什么:
逐条阅读,英文不太糟糕的应该都没有障碍:
-
struct objc_class *isa; (最不好理解的)
指向另一个类的指针,这个“另一个类”是“元类”(metaclass)。�元类用来表述类对象本身所具备的元数据。“类方法”就定义于此,因为这些方法可以理解成类对象的实例方法。每个类仅有一个“类对象”,而每个“类对象”仅有一个与之相关的“元类”。(引自《Effective Objective-C 2.0》57页)(注意,“类对象”在这句话里是一个整体,而不是解释成类的对象) -
struct objc_class *super_class;
指向另一个类的指针,这个“另一个类”是超类,确立继承关系。 -
const char *name;
�实例名 -
long version;
版本 -
long info;
其他信息 -
long instance_size;
实例大小 -
struct objc_ivar_list *ivars;
实例变量列表,提供实例变量信息,比如类的实例有多少个实例变量。 -
struct objc_method_list **methodLists;
实例方法列表,提供实例方法信息,比如类的实例实现了多少个方法。 - *struct objc_cache cache;
缓存区 -
struct objc_protocol_list *protocols;
实例实现的协议
</br>
具体的例子总是更容易理解的,�现在从抽象到具体。
我自定义了一个类(btw,�许多人写博都喜欢把自定义的类叫SomeClass、MyClass、CustomClass等等,这些类名依然会让人感觉到很抽象),所以我自定义类会叫Kardel。
Kardel *myKar = [[Kardel alloc] init];
为了更直观,我把myK定义成id类型:
id myKar = [[Kardel alloc] init];
如上所言,id是一个指向objc_object结构体的指针,myK这个实例自然就是一个objc_object结构体了。然后,��根据我们上面所见,objc_object结构体——即实例里面只有一个成员变量,isa指针。它会告诉我们这个实例所属的类。
结论1:类的实例是objc_object结构体
</br>
结论2:类是objc_class结构体
</br>
结论3:objc_class结构体中还有objc_class,即类里面的类——“元类”
</br>
三者之间的继承关系:
还有值得思考的问题是为什么要这么做:实例里面没有存放很多信息(只有一个指针,靠其得知它是什么类),而类负责存放实例的信息,元类负责存放的是类的信息。