Objective-C 类的实质是结构体

96
KardelShaw
2016.12.14 18:21* 字数 736

id类型是什么:

objc/objc.h

可见id是一个指向objc_object结构体的指针。

看一条语句就清晰了:

id obj = [[NSObject alloc] init];

所以对象obj就是一个objc_object结构体。它们都有个成员变量isa,其类型为objc_class。它又是一个指针,指向objc_class结构体,那么下面再看objc_class里面有什么。

objc_class是什么:

objc/runtime.h

逐条阅读,英文不太糟糕的应该都没有障碍:

  • 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>
三者之间的继承关系:

Numbers绘图(改自《Effective Objective-C 2.0 图2-6》)

还有值得思考的问题是为什么要这么做:实例里面没有存放很多信息(只有一个指针,靠其得知它是什么类),而类负责存放实例的信息,元类负责存放的是类的信息。

Objective-C