5

在 Objective-C 的旧版本中,objc_class 结构体是这样实现的:

struct objc_class {
    Class isa;
    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;
};

因此,表示对象的结构存储了指向对象类的指针,指向对象超类的指针,对象的类名,对象的版本,信息和实例大小,对象的实例变量列表,对象的方法列表,对象的缓存和对象的协议列表。结构中代表对象的这些字段的存在是很容易理解的,因为它们中的每一个都存储有关对象的信息。

然而,相同结构 objc_class 的 Objective-C 2.0 实现是这样的:

struct objc_class {
    Class isa;
};

因此,在这个版本的 objc_class 中,结构中只有一个字段:指向对象的类结构的指针。

那么,我的问题是,关于对象的其他信息如何存储在 Objective-C 2.0 中,因为结构中只有一个字段表示对象?

4

1 回答 1

7

这一切都在新的(好吧,不再那么新)非脆弱的 ABI 中了。

基本上,编译器不会像以前那样将 iVar 存储在结构中(如果超类更改了它的 iVar 布局,这会破坏继承),编译器会将 iVar 重定向通过另一层,类似于objc_setAssociatedObject在运行时。

这允许一些有趣的场景。考虑以下:

@interface A { // part of libA.a
   id var1;
   int var2;
   float var3;
} 

@end

@interface B : A { // part of libB.a
   id var4;
}

@end

现在,如果某个时候,我们需要更改 class A,并且我们确定我们需要更高的精度var3(例如,将其转换为 a long double)怎么办?

在旧的、脆弱的 ABI 中,我们会被搞砸,直到libB更新的制造商。然而,有了这个新的、非脆弱的 ABI,我们可以灵活地改变所有这一切,同时libB仍然有效。

虽然理论上这可能会慢几个周期,但它增加了在运行时查找 iVar 的更简单方法、更灵活的子类化以及对不同类型 iVar 的支持(__weak例如)。

于 2012-08-07T00:07:52.043 回答