Objective-C理解isKindOfClass

And*_*y M 2 casting objective-c nsnumber

最新版本的Objective-C和XCode(4.4).

我有一个代码片段,我无法理解为什么我能够使用某些行,让我解释一下:

// For understanding purpose : (NSMutableArray*)_programStack

id l_topItemOnStack = [_programStack lastObject];
if([l_topItemOnStack isKindOfClass:[NSNumber class]])
{
    return [l_topItemOnStack doubleValue];
}
Run Code Online (Sandbox Code Playgroud)

我的问题:因为我l_topItemOnStack的类型id而且我没有把它变成一个NSNumber,我怎么能用到[l_topItemOnStack doubleValue].

我猜我必须首先将其转换为NSNumber以访问NSNumber方法...

我在这里错过了什么?

小智 7

因为Objective-C是一种动态语言,所以消息名称及其声明只是编译器的提示 - 实际的消息查找和发送在运行时发生.因此,即使编译器不知道您的对象响应doubleValue消息,它仍然可以进行调用

return objc_msgSend(l_topItemOnStack, @selector(doubleValue));
Run Code Online (Sandbox Code Playgroud)

和往常一样.

此外,编译器查找在包含的头中任何地方声明的所有选择器,并尝试使用实际上下文找到最佳匹配 - 这里doubleValue是一个唯一名称 - 它仅在NSNumber上声明,因此编译器假定您的对象确实是一个NSNumber.

如果你真的想避免这种情况,可以在调用方法时强制转换对象,或者最初将其声明为NSNumber.

  • @AndyM没问题.这是一个相当奇怪的隐藏细节(​​我甚至不认为编译器会做这种不雅的诡计).顺便说一下,这可能不是Xcode为您提供自动填充建议的原因 - **Xcode不是编译器**. (2认同)