tags:

views:

279

answers:

4

If I create a custom initWith for an object do I essentially include the code I would add should I want to override init?

-(id) init {
    self = [super init];
    if (self) {
        NSLog(@"_init: %@", self);
    }
    return(self);
}

e.g.

-(id) initWithX:(int) inPosX andY:(int) inPosY {
    self = [super init];
    if(self) {
        NSLog(@"_init: %@", self);
        posX = inPosX;
        posY = inPosY;
    }
    return(self);
}

gary

+3  A: 

Yes, that's exactly how I do it. One slight change will cut out a line of code:

 if (self = [super init]) {

As opposed to:

 self = [super init];
 if(self) {
Benjamin Cox
GCC with warnings enabled will complain, because `=` in `if` is more commonly used by accident than intentionally. I would write it the way OP has it now, but to silence the warning, `if ((self = [super init]))` (note the extra parentheses) will do.
ephemient
so you like to copy the same initialization code to all 150 different initialization methods that you have for this really complex class?
stefanB
No, stefan, I generally do what you do. The way I read his example was to change init: to initWithX:andY:, rather than adding initWithX:andY:, so didn't get into this aspect. But it is a great point, glad you made it!Thanks, ephemient, for the comment. I had always wondered why code examples often did that, since it builds alright without it. Apparently in my XCode hadn't ever gotten all the warnings enabled. You've inspired me!
Benjamin Cox
+3  A: 

I'd suggest creating one main initializer that handles most of the work. You can then create any number of other initializers that all call this main one. The advantage of this is if you want to change the initialization process, you'll only have to change one spot (in general). It might look like this:

-(id) initWithX:(float)x {
    if (self = [super init]) {
        /* do most of initialization */
        self.xVal = x;
    }
    return(self);
}

-(id) init {
    return [self initWithX:0.0f];
}

In this example initWithX: is our main initializer. The other initializer (init) simply calls initWithX: with a default value (in this case 0).

dbachrach
Your `init` should return the result of [self initWithX:0.0f].
Anthony Cramp
Yep, missed that. Fixed. Thanks.
dbachrach
+6  A: 

You can create one designated initializer that accepts all parameters that you want to make available in initialization.

Then you call from your other -(id)init your designated initializer with proper parameters.

Only the designated initializer will initialize super class [super init].

Example:

- (id)init
{
    return [self initWithX:defaultX andY:defaultY];
}

- (id)initWithPosition:(NSPoint)position
{
    return [self initWithX:position.x andY:position.y];
}


- (id)initWithX:(int)inPosX andY:(int)inPosY
{
    self = [super init];
    if(self) {
        NSLog(@"_init: %@", self);
        posX = inPosX;
        posY = inPosY;
    }
    return(self);
}

The designated initializer is -(id)initWithX:andY: and you call it from other initializers.

In case you want to extend this class you call your designated initializer from subclass.

stefanB
A: 

Sometimes, you want to reuse some initialisation code and modify the behaviour only slightly for specific initialisers. In this case, I do the following:


- (id) init
{
    self = [super init];
    if (!self) return nil;

    // These values are always initialised this way
    ivar1 = 10;
    ivar2 = @"HellO";
    ivar3 = [[NSMutableArray alloc] initWithCapacity:10];
    ivar4 = 22;

    return self;
}

- (id) initWithIvar4:(int) aValue
{
    // call -init on self, which will call -init on super for us, and set
    // up ivar1, ivar2, ivar3, and ivar4.
    self = [self init];
    if (!self) return nil;

    // Change ivar4 from the default 22 to whatever aValue is.
    ivar4 = aValue;

    return self;
}

dreamlax
That's another option, but in case where you call only init you end up with ivar4 not being initialized, and you will have to remember that in that specific initializer you don't initialize some variables but other initializers do initialize them ... sounds a bit too much error prone to me ...
stefanB
Sorry, I didn't provide a very decent example. This code was designed to accept that `ivar4` has a default value of 0, unless specifically set with `initWithIvar4:`. You could just as easily set `ivar4` in `-[self init]` too, but you're right, you could easily end up with some variables initialised and some not, and not easily being able to trace where certain variables are set.
dreamlax
Edited code to make it more sensible.
dreamlax