A philosophical answer about alloc/init.
init is not a constructor. Conceptually, "construction" does not exist in Objective-C. In Java (and other languages with constructors), calling the constructor will return a new instantiation of the object that is ready to go. There is no exact equivalent to this in Objective-C. (One could argue that convenience class methods such as +array, +arrayWithObjects, etc are technically constructors since they wrap both allocation and initialization, but I would argue that they're still not constructors in the same sense as Java constructors.)
What we have instead is the concept of allocation and initialization, two distinct steps that, when executed together, act as if they were a "constructor". The class method +alloc simply requests an appropriately sized chunk of memory from the system. IIRC, it uses the calloc() function to do so. It is not guaranteed that any zeroing will take place during the execution of the alloc function. This means that we need to do the initialization ourselves, which we do by immediately calling an -init method.
HOWEVER, -init (and all derivatives) are nothing more than ordinary instance methods. You can message them whenever you want in order to "reset" an object instance to its original initialized state (although there are some memory management ramifications of doing this that must be taken into account). It also means that you can do something ridiculous like this:
NSUInteger count = [[[NSArray alloc] autorelease] count];
I can't think of a good reason why you'd want to do this, but the point is that you can. It further goes to emphasize that init is not a constructor. In the example above, the object exists by the time the +alloc method returns. However, it may not be properly initialized, which means that the unsigned integer "count" might not be zero. It could be, but it would be incorrect to rely on that behavior (unless otherwise documented, of course).
One of the advantages of breaking construction into allocation and initialization is we can have a large degree of control over exactly what's getting initialized. In Java, for example, you can only have one constructor per method signature. In other words, if you have a constructor that takes a single "Object" argument, then that's the only constructor that can. You cannot create another constructor that also takes a single Object argument.
In Objective-C, parameter types are not part of the method signature (known as a "selector"), and so I can create an initializer like so:
- (id) initWithAnObject:(id)anObject;
However, I can also create another initializer:
- (id) initWithADifferentObject:(id)anObject;
I can set these up to do totally different initializations of the object on which they're invoked. This is unbelievably useful!
Another really useful aspect of splitting construction into allocation and initialization is that you can chain initializers. AFAIK, you can't call constructors from within constructors in languages like Java (well, you can, but it doesn't have the same effect). In Objective-C, however, you can do something like this:
- (id) initWithCapacity:(NSUInteger)initialCapacity {
if (self = [super init]) {
[self setInitialCapacity:initialCapacity];
}
return self;
}
- (id) init {
return [self initWithCapacity:0];
}
Now when you alloc/init an object set up like this, it will "redirect" and use the initWithCapacity initializer, even though you called init. (This is how NSArray's init method works) This means you can use conditional initializers. For example, have your -init method dispatch to one initializer under certain conditions but use a different one under different conditions.
In summary, the Objective-C model of "allocate and initialize" is much more powerful than the idea of construction. You, as the programmer, have a much greater degree of control over the initial setup phase of your object. It is a really liberating shift.
Cheers,
Dave
ps - init is not a constructor! ;)