A form of dynamic binding
Objective C is very fond of the idea that methods are not functions, but messages; that instead of objects being C++-style hunks of data that you operate controls on, they are autonomous entities that you ask to do things. This mindset is plain in the fact that you cannot manually declare and handle static instances of objects-- you can only work with pointers to them-- and in the Objective C "messaging syntax" for calling methods. The messaging syntax, patterned after SmallTalk, comes in the form [object method: argument]; compare that to the C++ object->method(argument), and consider the tiny psychological difference between the two.
The thing you may not have realized, however, is that the "messages" are not just a metaphor-- you call an objective c methods as if you were calling a function, but you aren't, not really-- you really are sending the object a message and asking the object to act on it. [object method: argument] is not mere syntactic sugar for object->method(argument) (which is nonsense in ObjC anyway), but rather something a bit more complex. In reality, [object method] is mere syntactic sugar for:
objc_msgSend(object, selector, argument);
(If you were for some reason to do this manually, selector
would actually be @selector( method )
. See selector
objc_msgSend is quite probably the most important thing in Objective C, and is never, ever meant to be called directly. Most of the dynamic features that make Objective C so elegant and useful (as well as a decent degree of slowdown) are possible as a result of the existence of this function. Method calling is handled by (instead of clumsily hardwired prelinked functions) an intelligent runtime process that looks at the runtime-generated isa variables and attempts each of the following until something works:
- Checks to see if the object has an implementation of the requested selector. If so, calls it.
- Failing that, does the same check to each of the object's superclasses in turn until it finds an implementation or reaches NSObject.
- Failing that, sends the object a forwardInvocation message.
- Failing that, produces an error.
This process has a couple of interesting consequences. Most notably, the horrific "Fragile Binary
" problem C++
has is completely absent in Objective C
. Instance variables in an object are requested using messages, the same way as methods are (This doesn't sound like much, but it's a huge deal. Watch people who write C++
-- usually, because writing accessor functions
is such a hassle, they will simply declare their variables public
and then let anyone reach in and mess with them directly-- neatly negating the data encapsulation
features that make the language worthwhile in the first place. In objective c, meanwhile, a request for a variable is indistinguishable from the outside from a request for an accessor function.)
The forwardInvocation:(NSInvocation *)anInvocation message, though, is perhaps the most interesting bit of all. The message, sent whenever an object is asked to handle a selector it does not implement, gives you the ability to create a kind of a "default" function, to set up catch-all cases that deal with the inappropriate message in any number of ways. For example, if you so wished you could have forwardInvocation display an error message specifically saying that the object has been sent a message it does not understand, and give the messages' name (it is possible to get the character names of objective c methods at runtime). The more common use, though, is one of Objective C's most powerful concepts: message forwarding, the basis of Proxy objects. Once you have received the forwardInvocation message, it is possible to simply pass the invocation on to another object-- allowing you, for example, to create surrogate objects that appear to be taking all messages but are, in fact, having a completely other object handle them. For example, NeXTStep provides a manner of calling methods in objects on *remote computers*, using proxy objects on both ends that encode the NSInvocation into TCP/IP, send it to the remote computer, decode it, and forward it to the appropriate object.
If you absolutely have, for some reason, to go around the messaging system and call a method directly, send the object that defines the method the methodForSelector:(SEL)selector message, and it will return a pointer to the appropriate C function.