karim
karim

Reputation: 15589

objective C [self init] hierarchy for multilevel inheritance

I have class A which inherits class B. And want to achieve something like below. But the init methods get recursive call due to dynamic typecasting. Is there any way to achieve such? Any suggestion? (without changing 'init's name in subclass?

@interface A : NSObject
@property NSData * data;
@end

@implementation A

- (id) init {
    self = [super init];
    /* want to do some default initialization here  
       for this class and all of its subclasses. */
    // ... ... 
    return self;
}

/* This [self init] get recursed. 
   But how can I force this class and all of its subclass to call [self init] above, 
   not to call the subclass's init method. */

- (id) initWithData:(NSData *)d {
    self = [self init];
    self.data = d;
    return self;
}

@end

@interface B : A

@end

#import "B.h"

@implementation B

- (id) init {
    self = [super initWithData:nil];
    // some subclass specific init code here ... 
    return 
}
@end

Using B,

- (void) testInit{
    B * b = [[B alloc] init];
}

Upvotes: 1

Views: 1458

Answers (4)

karim
karim

Reputation: 15589

Here is an example of designated initilizer pattern mentioned above,

#import ”Person.h”

@implementation Person
-(id) initWithAge:(int)theAge AndHeight:(int)theHeight AndName:(NSString *)theName {
  if (self = [super init]){
    _age = theAge;
    _height = thefleight;
    _name = theName;
  }
  return self;
} 

-(id) initwithAge:(int)theAge AndHeight:(int)theHeight {   
  return [self initWithAge:theAge AndHeight:theHeight AndName:nil];
}

-(id) initwithAge:(int)theAge {
  return [self initWithAge:theAge AndHeight:0];
}  

- (id)init {
  return [self initwithAge:0];
}
@end

Upvotes: 1

Greg Parker
Greg Parker

Reputation: 8012

Look up the "designated initializer" pattern. It describes how to arrange initializer methods and convenience constructors (a.k.a. factory methods) in a class hierarchy.

Upvotes: 1

CodenameLambda1
CodenameLambda1

Reputation: 1299

You're calling [self init] in your implementation which is causing the recursion issue..

Implement this way :

- (id) init {
    self = [super init];
    //Basic empty init...
    return self;
}

- (id) initWithData:(NSData *)d 
{
    self = [super init]; //<---- check this line.

    if(self)
    {  
        self.data = d;
    }
    return self;
}

//If you are looking to write some init code only 1 time the the following can work.....

-(void)oneTimeWrittenInitCode:(id)mySelf
{
    //your init code which you wish to write one time goes here...
}    

- (id) init {
    self = [super init];
    if(self)
    {
       [self oneTimeWrittenInitCode:self];
    }
    return self;
}

- (id) initWithData:(NSData *)d 
{
    self = [super init];

    if(self)
    {  
        [self oneTimeWrittenInitCode:self];
        self.data = d;
    }
    return self;
}

Upvotes: 6

Rui Peres
Rui Peres

Reputation: 25917

It should be:

- (instancetype) initWithData:(NSData *)d
{
    if(self = [super init])
    {
       _data = d;
    }
    return self;
}

Upvotes: 0

Related Questions