Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are alloc and init called separately in Objective-C?

Note: I'm relatively new to Objective-C and am coming from Java and PHP.

Could someone explain to me why I always have to first allocate and then initialize an instance?

Couldn't this be done in the init methods like this:

+ (MyClass*)init {
    MyClass *instance = [MyClass alloc];
    [instance setFoo:@"bla"];

    return instance;
}

+ (MyClass*)initWithString:(NSString*)text {
    MyClass *instance = [MyClass init];
    [instance setFoo:text];

    return instance;
}
...

Is this just a relict from the old C days or is there something that I'm not seeing?

I know this isn't a problem as I could as well always call alloc and init, but since it's a bit tedious I'd like to at least know why I'm doing it.

I'm liking the expressiveness of the language so far, but this is something that I want to fully understand in order to think the Objective-C way.

Thank you!

like image 652
André Hoffmann Avatar asked Sep 06 '09 11:09

André Hoffmann


2 Answers

+new ends up sending an +alloc message to the class and an -init message to whatever comes back from +alloc.

The reason that NeXT departed from Stepstone's convention of using the +new message (which was a Smalltalk idea) is that early on, they encountered situations where they wanted to be able to initialize the same object more than once.

like image 124
NSResponder Avatar answered Oct 21 '22 10:10

NSResponder


Because creating an instance and initializing an instance are two separate jobs.

You send an alloc message to the class to get an uninitialized instance. You must then initialize the instance, and you often have several ways to do that. For example:

myStr = [[NSString alloc] init]; //Empty string
myStr = [[NSString alloc] initWithFormat:@"%@.%@", parentKeyPath, key];
myStr = [[NSString alloc] initWithData:utf16data encoding:NSUnicodeStringEncoding error:&error];
myStr = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error];

Each of these initializes the string in a completely different way. How you initialize the string depends on what you want to initialize it from.

Of course, nobody likes writing alloc and then init and then autorelease every time, so you usually have convenience methods (e.g., stringWithFormat:) that do all three steps for you.

Edit: For more on this topic, including essential insights from commenters, see my blog post “Reunification”.

like image 32
Peter Hosey Avatar answered Oct 21 '22 09:10

Peter Hosey