What's the difference between dot syntax and square bracket syntax?
I am going through some walkthroughs fpr Objective-C and I got to many places where I raised my eyebrows. I would love to get them down.
Is there a fundamental difference in message sending and method calling? Objective-C lets me do both:
object.message
yields the same result as[object message]
. I think maybe nested messages cannot be created using the dot operator strategy?-
I created an
NSArray
object, now I am about to print results for this using anNSEnumerator
:id myObject = [object objectEnumerator];
in a while loop iterating and printing results. The type of
myObject
isid
, which means it's resolved at runtime and not compile time. I know very clearly what kind of objects are stored in myNSArray
—they areNSString
s—so by changing the type ofmyObject
toNSString * myObject
, it works just fine. However, I experimented and found out thatmyObject
can be of any type, be itNSString
orNSArray
orNSEnumerator
, and any of these work just fine, perfectly iterating theNSArray
object and yielding the same results. What's up with that?
I'm not sure what kind of distinction you're trying to make between "message sending" and "method calling", since they're two ways of describing the same thing. The dot syntax is just a shortcut for calling getters and setters, that is:
[foo length]
foo.length
are exactly the same, as are:
[foo setLength:5]
foo.length = 5
You should generally only use the dot syntax when you're using getters and setters; use the square bracket syntax for all of your other method calls.
For your second question: this is how dynamic typing works. Any type declarations you put in your code are hints to the compiler; your Objective-C method calls will always work as long as the objects respond to them.
It's a distinction oriented at the person reading your code. Dot syntax indicates state (I'm accessing an ivar), method syntax indicates behavior (I'm performing some action). To the runtime, both are the same.
I think Apple's intention is to show accessors as an implementation detail you shouldn't worry about. Even when they could trigger side effects (due to some additional code in the accessor), they usually don't, so the abstraction is imperfect but worth it (IMHO). Another downside of using dot notation is that you don't really know if there is a struct or a union behind it (which unlike message sending, never trigger side effects when being assigned). Maybe Apple should have used something different from a dot. *shrugs*
I think maybe nested messages cannot be created using the dot operator strategy?
Dot notation can be used to nest calls, but consider the following:
shu.phyl.we.spaj.da
[[[[[shu]phyl]we]spaj]da]
In this case, the uglier, the better. Both are a code smell because one object is creating dependencies to another object far far away, but if use brackets to pass messages you get that extra horrible syntax from the second line, which makes the code smell easier to notice. Again, convention is to use dots for properties and brackets for methods.
1: Your terminology is incorrect. The dot operator is not "method calling", a different operation. It's just a different visual appearance for message sending. There's no difference between [x y] and x.y. The dot syntax can only take one argument though, as it's intended to be used only for property access.
2: The static (compile-time) type of an object has no effect on its behavior at runtime. Your object is still an NSEnumerator even if you're calling it something else.