Possession init method


#1

When overriding Possession’s -init method, why do we call -initWithPossessionName:valueInDollars:serialNumber: instead of calling -initWithPossessionName:? Won’t those two calls evaluate to the same thing, a possession whose name is “Possession” with a value of 0 and a serial number of “”? Is it more expensive to let a call work down a chain? Am I missing something?


#2

Yes, it is more expensive to “call down a chain,” simply because of the number of messages that will be sent. But let’s clear up some terminology: the initializer chain is not all of the initializer methods that make up one classes suite of initializers. The initializer chain is the designated initializer of a class and all of its superclass’ designated initializers combined.

It just so happens that in this example, Possession’s initializers are all kind of related and the semblance of a “chain” is there. (When in fact, the initializer chain is Possession’s designated initializer and NSObject’s designated initializer.) In many cases, the initializers of a class won’t be so related. (You could imagine having a Connection class that had initializers for an already existing socket, a IP/port address, or an existing streaming connection, for example.) In those cases, you wouldn’t have the option of calling another initializer that eventually calls the designated initializer.

However, the real reason you don’t want to chain together initializers within a class is because you then rely on the behavior of more than one method to do your work. Should you ever decide to remove or change one of the intermediate initializers, you will have to do some work to “relink” any other initializers back in to the chain.

This is the focus of the designated initializer design pattern: you can only make mistakes in one place and you won’t accidentally miss an instruction in similar initializers. I like to think of this graphically, the designated initializers make a beacon of light in the center traveling up to the all-mighty NSObject, while the other initializers are bowing down and paying homage around that beacon of light at different levels.

I’m also a pretty odd dude, so you might have another less awkward metaphor.


#3

Thanks, Joe! That makes perfect sense. And your metaphor is brilliant.


#4

I’m not sure part of the question was answered? Wouldn’t this be cleaner? Seems to work on my machine.

  • (id)init
    {
    return [self initWithPossessionName:@“Possession”];
    }

David


#5

[quote=“darnold”]I’m not sure part of the question was answered? Wouldn’t this be cleaner? Seems to work on my machine.

  • (id)init
    {
    return [self initWithPossessionName:@“Possession”];
    }

David[/quote]

In this particular example it works and appears cleaner, but that’s due to coincidence rather than better or more efficient coding. The purpose of overriding init is to make sure that it calls the designated initializer for your class. The “chain” should consist of: designated initializer for class —> designated initializer for superclass —> … —> designated initializer for NSObject (init)

Introducing any other initializers into that chain can cause several problems including dependency on the additional initializer and any intermediaries, as well as unnecessary messages being sent by having a side chain.