After experimenting with Objective-C for a while now, I find the language is gradually growing on me. It’s still a bit strange in some spots, and I have a lot left to learn, but it’s starting to make sense. One of the things I really like about the language is a feature lifted from Smalltalk: using “infix” syntax to send a message.
// invoking a MyCalculator method (by sending it a message)
int sum = [MyCalculator add:29 to:13];
In my previous post I touched on what it means to send a message in Objective-C. I explained that method calls on a class or object are mediated by a message dispatcher at runtime. This means that method calls are more involved than just dereferencing a function pointer. A lookup process occurs, the results of which are cached for subsequent messages. Objective-C is a superset of traditional C, so you can still call global functions without sending any messages. Messages only enter the picture when you start dealing with the object-oriented features of the language.
The message being sent above ends up causing a class method to be called on the MyCalculator class. Objective-C refers to them as “class” methods, not “static” methods like in C#. The name of the method is add:to: which might take a moment to digest. As you saw in the code snippet, the method name is broken apart and woven into the argument list. When you refer to the method, you add all of the pieces together, including the colons. If the method didn’t take any parameters you would omit the colon altogether.
Here’s the declaration of the MyCalculator class:
#import <Cocoa/Cocoa.h>
@interface MyCalculator : NSObject
+ (int) add:(int) left to:(int) right;
@end
The + sign indicates that add:to: is a class method. The first (int) means that this method returns an integer. The rest of the line is the method name, intermixed with the argument list. I find this style of naming a method to be very intuitive, after getting used to it. I find myself thinking about naming methods based on the parameters much more carefully and making interesting decisions that I’d never make in C#.
In case you’re interested, here’s the implementation of the MyCalculator class:
#import “MyCalculator.h”
@implementation MyCalculator
+ (int) add:(int) left to:(int) right
{
return left + right;
}
@end
See you next time!
I like that syntax (add:29 to:13), even though it’s a bit verbose. I can’t help but think of .NET fluent interfaces, although I’m not so much a fan of those.
Thanks for the post Josh.
Cheers,
Daniel
When I was looking into obj-c, this message passing was the most interesting part to me. Questions that stumped me are: How much of a performance difference there is between passing a message vs the C++ way of vtable lookup. What does a message pass look like at the assembler level? Also, how is inlining affected?
Yes, I second that question. Is there any profile data between the global calls and calls to an object? I assume there’s some sort of fast-path caching going on. Does this mean that no object calls are ever inlined? Are property setter/getters treated as a special case?
Assuming that the messages are parsed at compile time (famous last words) the overhead might be close to early bound method calls of COM days. If so it is not much and you would only worry about them in performance critical places like inner loops.
These are all very good questions that I don’t know the answer to yet.
Message passing is quite fast but not as fast as c++ vtable lookups. When I started my objective-c journey I searched around a bit and found this: http://www.mikeash.com/pyblog/performance-comparisons-of-common-operations-leopard-edition.html
The above blog (no it’s not my blog:) also has some other nice cocoa and objective-c stuff , including http://www.mikeash.com/pyblog/friday-qa-2009-03-20-objective-c-messaging.html
Personally I have never found the message passing to be a performance problem but I’m no expert and usually only do UI stuff. And you can always mix c++ and objective c in 1 program if performance does matter…
Thanks for the info, Milander.