This might come as a surprise to most programmers, even experienced programmers – in Objective C, messages can be sent safely to nil references.
NSString *name = nil;
NSInteger length = [name length] // length = 0. Surprised?
This is perfectly legal. Another surprise, length has a valid value, zero, and not any garbage value.
Hope your interest is perked up. Let us first set the context for this discussion by comparing other languages.
Behaviour in C is pretty well known, SEGMENTATION FAULT which invariably crashes the program unless the SEGSEV signal is handled. Even if its handled there is nothing much that could be done because there is no way to go back to the previous point of execution.
Now Java tames this ugly beast. An exception is raised and if it is handled properly, the application can even continue execution. But the code becomes ugly with so many try-catch blocks littered all over even while dealing with simple operations.
Objective C completely tames the beast, it not only not crashes, but the programmer could be almost assured that the return value might be valid. This seems a bit vague but there are rules which govern the value returned by messages sent to nil objects.
- If the method returns an object, any pointer type, any integer scalar of size less than or equal to sizeof(void*), a float, a double, a long double, or a long long, then a message sent to nil returns 0.
- If the method returns a struct, as defined by the Mac OS X ABI Function Call Guide to be returned in registers, then a message sent to nil returns 0.0 for every field in the data structure. Other struct data types will not be filled with zeros.
- If the method returns anything other than the aforementioned value types the return value of a message sent to nil is undefined.
In short, return values from messages to nil objects are guaranteed to return the equivalent of zero for scalar return types, i.e., nil, 0, 0.0, NO, etc.
One disadvantage of this behavior is that bugs may go unnoticed. Objects which should not be nil might be nil but the code might behave as if nothing is wrong and it is tough to catch bugs in early stages of development.
But beware, sending messages to nil should not be confused with sending messages to deallocated instances.
[obj release] //assume retain count becomes 0 and object is released.
The above code releases object but does not nil the reference variable. Any messages sent to this reference variable will invariably lead to a crash.
This proper way of releasing an object is
[obj release]; // assume retain count becomes 0 and object gets released
[obj doSomething] // perfectly safe
The same effect maybe achieved using
self.obj = nil // assuming the property is declared with retain property
But this might cause KVO invocations which might not be needed.
All in all, the main advantage (maybe the only) advantage with this behavior is that code gets simplified and becomes more intuitive. Unnecessary checks which get littered all around can be avoided keeping the code more readable. In case an explicit check is required, the programmer can go ahead and add it anyway. So all in all, I think objective C has a good way of handling nil objects and maybe other languages could adopt it.