这个问题来自我刚刚添加到这个问题的答案的评论,但它不应该是重复的。
@Bavarious 对这个问题的回答对我来说很有意义,但我仍然很困惑,为什么即使对象是 id,运行时也无法将方法绑定到正确的对象?据我了解,dynamic binding
还是dynamic typing
编译器无法知道 id 背后的对象是什么,但运行时应该知道这一点并选择正确的对象作为消息的接收者。但为什么运行时不能这样做?
这个问题来自我刚刚添加到这个问题的答案的评论,但它不应该是重复的。
@Bavarious 对这个问题的回答对我来说很有意义,但我仍然很困惑,为什么即使对象是 id,运行时也无法将方法绑定到正确的对象?据我了解,dynamic binding
还是dynamic typing
编译器无法知道 id 背后的对象是什么,但运行时应该知道这一点并选择正确的对象作为消息的接收者。但为什么运行时不能这样做?
简答:C。
扩展:当编译器生成对方法的调用时,它实际上只是生成对 C 函数的调用——对 objc_msgSend() 或其中的变体——动态绑定和分派该方法。
因为 C ABI “在金属上”运行(非常接近),所以参数和返回值的传递方式可能会根据类型发生巨大变化。例如,编译器可以在寄存器中传递最大为 32 位的任何内容(或在某些体系结构中为 64 位),但任何更大的内容都将在堆栈本身上。
正因为如此,编译器不一定会发出一个通用的程序集来调用 objc_msgSend()——通过 (id) 来分派方法调用——作为不同的签名——方法的不同参数类型——可能需要不同的代码生成。
现在,从技术上讲,编译器可以在许多情况下生成相同的代码,但它选择采取保守的策略并抱怨。特别是,假设如果您有 2 个冲突的类型声明,则可能还有其他声明,并提醒您使用具有不同参数类型的同名方法是非常不鼓励的。