在旧版本的 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;
};
因此,表示一个对象的结构存储了指向对象类的指针、指向对象父类(super class)的指针、对象的类名、对象的版本、信息和实例大小、对象的实例变量列表、对象的方法列表、对象的缓存和对象的协议(protocol)列表。这些字段在表示对象的结构中的存在是非常容易理解的,因为它们中的每一个都存储了有关该对象的信息。
然而,同一个struct objc_class的Objective-C 2.0实现是这样的:
struct objc_class {
Class isa;
};
因此,在这一版本的 objc_class 中,结构中只有一个字段:指向对象的类结构的指针。
那么我的问题是,由于结构中只有一个字段表示对象,所以关于对象的其他信息如何存储在 Objective-C 2.0 中?
最佳答案
这一切都在新的(好吧,不再那么新了)非脆弱的 ABI 中。
基本上,编译器不是像以前那样将 iVar 存储在结构中(如果父类(super class)更改它的 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
现在,如果一段时间后,我们需要更改类 A
,并且我们确定我们需要更精确的 var3
(将其转换为 >long double
,例如)?
在旧的、脆弱的 ABI 中,我们会被搞砸,直到 libB
的制造商更新。然而,有了这个新的、非脆弱的 ABI,我们可以灵活地改变所有这些,同时 libB
仍然有效。
虽然理论上这可能会慢几个周期,但它增加了在运行时查找 iVar 的更简单方法、更灵活的子类化以及对不同类型 iVar 的支持(例如 __weak
)。
关于objective-c - 实例变量和方法如何存储在 Objective-C 2.0 对象中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11837589/