2010-01-16 117 views
8

好吧,我有一种感觉,你们能够快速指出为什么我对此感到困惑,但我有一个问题,为什么以下不会导致编译器错误或警告:Objective-C类型推断

NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ]; 

selectedObjectNSObject,和name恰好是int类型的@property的名称。

什么困扰我的是为什么编译器是完全愿意承担的[ self.selectedObject valueForKey:name ]返回的结果是NSNumber *型(不带类型转换的话),以便与以integerValue调用链的消息。显然,KVC将非对象“数字”类型封装到NSNumber中,但编译器无法知道-valueForKey:在此特定情况下将返回NSNumber *

为什么不会导致编译器警告沿着“id”行可能不会响应“-integerValue”?

回答

10

我希望我说得对:这是因为id是“特殊的”。 id类型的对象可以发送任何您想要的消息,编译器不会执行检查,并且会在运行时检查所有内容。换句话说,id类型是Objective-C的“动态类型”部分,而所有其他类型(如NSObject)是“静态类型”部分。

这样,您可以选择要使用静态打字的位置以及要使用动态打字的位置。这是完全合法的,做这样的事情:

id str1 = @"Hello"; 
id str2 = [str1 stringByAppendingString:@", world"]; 

但通常你输入字符串“紧密”为NSString S,因为你得到编译时静态类型检查的方便,只能求助于动态类型,其中静态的会妨碍,就像valueForKey的情况。

+0

谢谢!我有一种感觉,它与'id'是Objective-C中的特权类型有关。 :)我的倾向是总是在任何可能的时候都紧紧打字,所以我想我从未遇到过这种看似奇怪的行为。猜猜这使得'id'既强大又危险。我想知道在处理'id'的时候给类似的编译器提供一些上下文是否更好,或者如果你对'id'将会变成什么会产生积极的影响(如我的例子中的情况那样) 。 – LucasTizma 2010-01-16 08:36:42

+0

大拇指的规则是:“尽可能静态输入,需要时动态输入。”(您可以通过谷歌获得更多信息。)在这种情况下,我不会强制转换,它只会使表达式难以阅读。有时候你必须注释以帮助编译器选择正确的方法 - 请参阅http://stackoverflow.com/questions/1113270。 – zoul 2010-01-16 08:52:10

+0

感谢您的链接。我遇到了一些令人讨厌的小错误,这是由于方法命名导致与现有SDK方法名称“冲突”的结果。认为编译器对我很疯狂。 :)是的,我完全支持“尽可能静态打字,需要时动态打字”的理念。现在,如果只有Objective-C会添加对类型化集合的支持......看起来往往不是,我知道我的集合将要存储什么。 – LucasTizma 2010-01-16 09:08:39