我对Objective-C中的动态类型如何工作感兴趣。我一直在研究“id”类型,我知道它的作用以及如何使用它,但我很好奇......这些功能如何在引擎盖下实现?
在编译期间,仅在运行时期间无法确定/解决任何问题。我想它可以简单地指向内存中某个对象的第一个字节,但是如何存储类签名?它是如何知道它当前指向的是什么以及它如何为尖头对象的类实现各种getter?
答案 0 :(得分:15)
“引擎盖下”,可以这么说,所有Objective-C对象都是C结构,带有指向表示其类型的Class对象的指针。 id
是指向最基本的结构的指针,它看起来像这样:
struct objc_object {
Class isa;
}
id
由编译器专门处理,因为编译器不会向您发出任何警告,表明对象可能不会像使用更强类型的变量时那样响应任何选择器。
当你在任何一个对象上调用一个方法时,它会跟随isa
指向Class对象的指针并查找该Class对象,以找到你试图调用的方法的选择器的实现函数。
答案 1 :(得分:7)
要添加到Anomie的答案,类如何存储它所回答的消息的表以及这些消息调用的代码位是完全不透明的。因此,在某种程度上,没有人能够准确回答Apple的实施方式,并且几乎可以肯定与GNU的实现不同。
但是,Apple的Objective-C Runtime Reference解释了运行时可以在C级别执行的所有操作。所以你可以看到有什么操作可以设置和查找。它是一个相对简单的系统,主要是一堆字典(在未反射的意义上)将一个事物映射到另一个事物,例如从选择器到IMP函数指针。如果表中有特定类的条目,则调用相关的东西。如果没有,则检查超类,考虑标准forwardingTargetForSelector:回退机制,依此类推。
除此之外,更具体的评论需要更具体的问题。有很多细节,比如键值观察是通过方法调用实现的(因此,运行时调整类将调用的C指针,以便setter成为调用真实setter并告知正在观察的人),但是它们只是记录的运行时的特定用途。