Objective-C 类型推断
好的,我有一种感觉,你们很快就能指出为什么我对此如此困惑,但我有一个问题,为什么以下内容不会导致编译器错误或警告:
NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];
selectedObject
是一个 NSObject
,而 name
恰好是 int
类型的 @property
的名称。
让我困惑的是为什么编译器完全愿意假设 [ self.selectedObject valueForKey:name ]
的返回结果是 NSNumber *
类型(没有对其进行类型转换)为了通过调用integerValue
来链接消息。
显然,KVC 将非对象“数字”类型包装成 NSNumber
,但编译器无法知道 -valueForKey:
将返回 NSNumber *在这种特殊情况下。
为什么这不会导致编译器警告“id
may not respond to '-integerValue
'”?
Okay, I have a feeling that you guys'll be able to quickly point out why I'm so confused about this, but I have a question as to why the following does NOT result in a compiler error or warning:
NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];
selectedObject
is an NSObject
, and name
happens to be the name of a @property
of type int
.
What perplexes me is why the compiler is perfectly willing to assume that the return result of [ self.selectedObject valueForKey:name ]
is of type NSNumber *
(without typecasting it) in order to chain the message with a call to integerValue
.
Obviously, KVC wraps up non-object "number" types into NSNumber
, but there's no way for the compiler to know that -valueForKey:
will return an NSNumber *
in this particular case.
Why doesn't this result in a compiler warning along the lines of "id
may not respond to '-integerValue
'"?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我希望我没猜错:这是因为
id
是“特殊的”。id
类型的对象可以发送任何您想要的消息,编译器不会进行任何检查,所有内容都将在运行时进行检查。或者,换句话说,id
类型是 Objective-C 的“动态类型”部分,而所有其他类型(例如NSObject
)都是“静态类型”部分。这样您就可以选择要在何处使用静态类型以及要在何处使用动态类型。这样做是完全合法的:
但通常你将字符串“紧密地”键入为
NSString
,因为你可以方便地进行编译时静态类型检查,并且只在以下情况下才使用动态类型:静态的会妨碍,就像在valueForKey
情况下一样。I hope I got it right: This is because
id
is “special”. Objects of theid
type can be sent any message you want, there is no checking done by the compiler and everything will be checked in runtime. Or, in other words, theid
type is the “dynamic typing” part of Objective-C, whereas all the other types (likeNSObject
) are the “static typing” part.This way you can choose where you want to use static typing, and where you want to use dynamic typing. It is perfectly legal to do something like this:
But usually you type the strings “tightly” as
NSString
s, because you get the convenience of compile-time static type check, and only resort to dynamic typing where the static one would get in the way, like in thevalueForKey
situation.时间过去了,由于
__auto_type
,我们现在有了更好的类型推断从 Xcode 8 开始可用。所以现在你可以做
更多
事实上,我非常喜欢这个,所以我为了方便起见,将其作为一个 Pod。
Time is passed and we have better type inference now thanks to the
__auto_type
available since Xcode 8. So now you can do
and much more
In fact, I liked this so much so I made this as a pod for convenience.