5.5. Object allocation and initialization

An object returned by alloc is in a known state: each instance variable of the object has the default value of its type (except the instance variables introduced by State, most notably isa, which is a reference to the object's class). The state of default values however is not necessarily a meaningful state. For example, if the specification of the Counter objects included that the first value normally returned by an instance is 10, the proper initial value of the current_value would be 9. Therefore, every object must be initialized after allocation. The default initialization method has no arguments; it is defined by State as


id
  init
{
  = self;
}

The conventional way of creating a new instance of a class is by invoking alloc and init in a single expression.


MyClass x = [[MyClass alloc] init];

If Counter objects would indeed return 10 as the first value returned from nextValue, the initialization method would look like this:


id
  init
{
  next_value = 9;
  = [super init];
}

Often, initialization of an object needs one or more arguments. An example of this is an initializer for the Counter class where the first value returned by nextValue can be specified.


id
  initWithValue int value
{
  next_value = value - 1;
  = [super init];
}

In case of multiple initializers, usually, one is the designated initializer and the other initializers can be implemented by invoking it. For example, if initWithValue were the designated initializer of a Counter, the init method could be implemented like this:


id
  init
{
  = [self initWithValue 10];
}

An advantage of this setup is that subclasses only need to override a single initializer, when necessary, instead of all or any number of them.

Always having to invoke two methods (alloc and some initializer) just to create a new object can become a burden. For this reason, classes can provide, through inheritance or by implementation, one or more allocators, which pack the allocation and initialization into a single method. For example, State provides new as the default allocator: new allocates a new object and invokes the default initializer.


instance (id)
  new
{
  = [[self alloc] init];
}

Using the allocator, objects can be created easier, though not faster since it involves an extra method call.


MyClass obj = [MyClass new];

Just like a class can have a different designated initializer than its superclass, it can also have a different designated allocator. The Number class for instance, provides an allocator with for easy allocation:


Number one = [IntNumber with 1];