【问题标题】:Objective-C Type InferenceObjective-C 类型推断
【发布时间】:2010-01-16 08:06:41
【问题描述】:

好的,我觉得你们可以快速指出我为什么对此感到困惑,但我有一个问题,为什么以下内容不会导致编译器错误或警告:

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

selectedObject 是一个NSObject,而name 恰好是@property 类型的int 的名称。

令我困惑的是为什么编译器完全愿意假设[ self.selectedObject valueForKey:name ] 的返回结果是NSNumber * 类型(不进行类型转换),以便通过调用integerValue 链接消息。

显然,KVC 将非对象“数字”类型包装到 NSNumber 中,但编译器无法知道在这种特殊情况下 -valueForKey: 将返回 NSNumber *

为什么这不会导致编译器警告类似于“id may not respond to '-integerValue'”?

【问题讨论】:

    标签: objective-c types inference


    【解决方案1】:

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

    这样你可以选择你想在哪里使用静态类型,以及你想在哪里使用动态类型。这样做是完全合法的:

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

    但通常你将字符串“紧密”键入为NSStrings,因为你可以获得编译时静态类型检查的便利,并且只在静态类型会妨碍的情况下使用动态类型,例如在valueForKey情况。

    【讨论】:

    • 谢谢!我感觉这与 id 是 Objective-C 中的特权类型有关。 :) 我的倾向是在任何可能的时候总是紧紧地输入东西,所以我想我从来没有遇到过这种看似奇怪的行为。猜猜这让id 既强大又危险。我想知道在处理id 时是否最好进行类型转换以给编译器一些上下文,或者如果您对id 将变成什么是肯定的(就像我的示例中的情况),是否完全可以忽略它.
    • 经验法则是:“尽可能使用静态类型,需要时使用动态类型。” (您可以谷歌以获取更多信息。)在这种情况下,我不会进行类型转换,它只会使表达式更难阅读。有时您必须进行类型转换以帮助编译器选择正确的方法——请参阅stackoverflow.com/questions/1113270
    • 感谢您的链接。由于方法命名与现有 SDK 方法名称发生“冲突”,我遇到了一些令人讨厌的小错误。以为编译器对我发疯了。 :) 是的,我完全支持“在可能的情况下进行静态输入,在需要时进行动态输入”的理念。现在,如果只有 Objective-C 会添加对类型化集合的支持……似乎更多时候,我知道我的集合将存储什么。
    【解决方案2】:

    时间过去了,感谢__auto_type,我们现在有了更好的类型推断 从 Xcode 8 开始可用。所以现在你可以这样做了

    #define let __auto_type const
    #define var __auto_type
    
    let a = @[@"pew pew"];
    var b = 2;
    b = a; //compiler warning "Incompatible pointer to integer conversion assigning to 'int' from 'NSArray *__strong const'"
    

    much more

    事实上,我非常喜欢这个,所以为了方便起见,我把它做成了一个豆荚。

    pod 'SwiftyObjC'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-05
      • 1970-01-01
      • 2010-10-03
      相关资源
      最近更新 更多