views:

123

answers:

1

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'"?

+4  A: 

I hope I got it right: This is because id is “special”. Objects of the id 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, the id type is the “dynamic typing” part of Objective-C, whereas all the other types (like NSObject) 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:

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

But usually you type the strings “tightly” as NSStrings, 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 the valueForKey situation.

zoul
Thanks! I had a feeling it had to do with `id` being a privileged type in Objective-C. :) My tendency is to ALWAYS tightly type things whenever possibly, so I guess I never encountered this seemingly strange behavior. Guess that makes `id` both powerful and dangerous. I wonder if it's better to typecast to give the compiler some context when dealing with `id`, or if it's perfectly fine to leave that out if you're positive of what `id` will become (as was the case in my example).
LucasTizma
The rule of the thumb is: “Static Typing Where Possible, Dynamic Typing When Needed.” (You can Google that to get further info.) In this case I would not typecast, it would only make the expression harder to read. Sometimes you have to typecast to help the compiler choose the right method – see http://stackoverflow.com/questions/1113270.
zoul
Thanks for the link. I've encountered some nasty little bugs as a result of method naming that happens to "conflict" with existing SDK method names. Thought the compiler was going crazy on me. :) And yes, I'm totally a proponent of the “Static Typing Where Possible, Dynamic Typing When Needed” philosophy. Now if only Objective-C would add support for typed collections... Seemingly more often than not, I know what my collections are going to store.
LucasTizma