Reputation: 1536
I had an exercise to override init method, so I need to create an init
method that will set some attributes as well.
My question is: why do I need to define the original init
method as well? in case that the new init
method won't work?
This is my .h
file:
#import <Foundation/Foundation.h>
#import "XYPoint.h"
@interface Rectangle: NSObject
@property float width, height, tx, ty;
-(XYPoint *) origin;
-(void) setOrigin: (XYPoint *) pt;
-(void) translate: (XYPoint *) point;
-(id) initWithWidth:(int) w andHeight:(int) h;
-(id) init;
@end
And .m
(only the init methods):
-(id) initWithWidth:(int)w andHeight:(int)h
{
self = [super init];
if (self)
{
[self setWidth:w andHeight:h];
}
return self;
}
-(id) init
{
return [self initWithWidth:0 andHeight:0];
}
I know that it is good this way, but if someone can explain me why is that I would be appreciated.
Upvotes: 4
Views: 6798
Reputation: 141879
The idea is to have a central point of initialization for your object instead of sprinkling the initialization of variables throughout each init method.
Your particular example doesn't do much justice to this pattern because you're initializing a Rectangle with 0 width and 0 height, and the default NSObject implementation resets the memory for all instance variables to zero by default, and your initWithWidth:andHeight:
method does the same. However, suppose that, you were allocating unit rectangles (width 1, height 1) by default when a Rectangle object was created using,
[[Rectangle alloc] init]
then instead of doing this,
- (id)initWithWidth:(int)width andHeight:(int)height {
self = [super init];
if (self) {
[self setWidth:width andHeight:height];
}
return self;
}
- (id)init {
self = [super init];
if (self) {
[self setWidth:1 andHeight:1];
}
return self.
}
you're centralizing the point of initialization by just doing,
- (id)initWithWidth:(int)width andHeight:(int)height {
self = [super init];
if (self) {
[self setWidth:w andHeight:h];
}
return self;
}
- (id)init {
return [self initWithWidth:1 andHeight:1];
}
This also goes hand in hand with the principle of DRY a.k.a. Don't Repeat Yourself.
This is a trivial example, however, in most real-world objects, you might have a much more complicated setup with notification registration, KVO registration, etc., and then it becomes absolutely crucial that your centralize all that initialization logic.
Upvotes: 5
Reputation: 28766
You don't have do. You generally have one initializer that calls super (self = [super initWithXX]) and the others defer to that one.
In your specific example above its a good idea because initWithWidth:andHeight is acting as the main initializer, so if you call the default what ever code that needs to run in the main initializer will get called.
Btw: Use of the word 'and' in your initializer parameters is a little archaic by modern Objective-C conventions.
Upvotes: 2