2013-10-28 73 views
1

我有繼承類B的類A,並且想實現類似下面的類。但是由於動態類型轉換,init方法獲得了遞歸調用。 有沒有辦法實現這樣的?任何建議? (無子類中改變「init的名字?多級繼承的客觀C [self init]層次

@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 

使用B,

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

「類似下面」 - 像什麼? 「由於動態類型轉換,init方法獲得遞歸調用」 - ??? – 2013-10-28 13:01:12

回答

6

你調用您的實現[self init]這是造成遞歸問題..

實現這種方式:

- (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; 
} 

//如果您正在尋找寫一些初始化代碼只有1次在以下能正常工作.....

-(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; 
} 
+0

是的,我知道。但是,如果我需要在超類中執行一些默認的初始化步驟,並且想要在超類中調用[self init]。那就是問題所在。然後它調用sublcass(動態名稱解析)。但是有什麼辦法可以阻止它嗎? – karim

+0

在您的子類的init代碼中調用[super init]時,將自動調用寫入您的超類的init。 – CodenameLambda1

0

它應該是:

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

查找「指定初始化程序」模式。它描述瞭如何在類層次結構中安排初始化方法和便利構造函數(又名工廠方法)。

+0

問題是指定初始化程序的行爲及其在子類中的重寫。如果[self init]或類似的東西被覆蓋,但是在超類中,如果它們中的任何一個被調用,它不會調用超類的超類,而是子類的超類方法。 – karim

1

下面是上述指定initilizer模式的一個例子,

#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 
+0

命名約定應當符合蘋果的指導方針 - (ID)initwithAge:(INT)theAge AndHeight:(INT)theHeight 應 更換 - (ID)initwithAge:(INT)theAge高度:(INT)theHeight 拆除並從方法簽名。 –