tags:

views:

257

answers:

3

I'm a bit puzzled:

  • From Cocoa Programming For Mac OS X (page 63, 3rd edition, Aaron Hillegass): "If it reaches the top of the [inheritance] tree without finding a method, the function throws an exception".

  • From the Wikipedia article on Objective-C: "the object to which the message is directed (referred to as the receiver) is not inherently guaranteed to respond to a message, and if it doesn't it simply ignores it and returns a null pointer."

Which one is it?

+4  A: 

They're both more or less correct. The difference is that the Cocoa framework defines root objects (e.g., NSObject) from which the other classes in the framework inherit; if an object doesn't respond to a message, by default it gets passed up the tree until it reaches a root object, which then throws an exception in Cocoa.

This behavior can be overridden to allow objects to do other things with messages they don't understand.

Other Objective-C frameworks can choose to deal with unrecognized messages in a different way (e.g., by returning a null pointer).

mipadi
+7  A: 

When a selector is not found, it will go to -[NSObject doesNotRecognizeSelector:]. The default implementation fires off an exception.

Tom Dalling
However, note that the contract for -doesNotRecognizeSelector: requires that if it is overridden, the new implementation MUST raise an NSInvalidArgumentException at the end.
Quinn Taylor
+1  A: 

In the case of Cocoa and NSObject, @Tom is correct — an exception is raised. When programming in Cocoa, trust the Cocoa experts first. The Wikipedia article is about the language ant runtime in general, and possibly accounts for behavior of GNUstep as well. The "ignore and return nil" behavior sounds more like what happens if you send a message to nil. It's hard to say whether the author was confused or trying to describe a default non-Cocoa behavior.

@mipadi also has a great point in that Objective-C allows you to handle invocations of unimplemented methods dynamically, including forwarding them on to arbitrary objects. For details, see NSObject's -methodSignatureForSelector: and -forwardInvocation: methods. If you want to dynamically supply methods in this way, it's worth taking a look at possibly overriding -respondsToSelector: too. (All these methods should be used only if you understand what they're doing, since they deeply affect how instances of your class interface with the Objective-C runtime, and can have unintended results.)

Note that the contract for -doesNotRecognizeSelector: requires that if it is overridden, the new implementation must raise an NSInvalidArgumentException at the end.


Edit: @Nikolai pointed out an awesome Mike Ash blog entry which "goes into even more depth about what's happening when the runtime does not find a matching selector." It's definitely worth a read. I wasn't aware of that post — thanks, Nikolai!

Quinn Taylor
Mike Ash has a great blog post about this topic. It goes into even more depth about what's happening when the runtime does not find a matching selector.http://www.mikeash.com/?page=pyblog/friday-qa-2009-03-27-objective-c-message-forwarding.html
Nikolai Ruhe