2013-02-18 29 views
4

我有一個練習來覆蓋init方法,所以我需要創建一個init方法來設置一些屬性。重寫`init`方法時,爲什麼重新定義它很重要?

我的問題是:爲什麼我還需要定義原始的init方法?如果新的init方法不起作用?

這是我.h文件:

#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 

而且.m(僅在init方法):

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

我知道,這是很好的這種方式,但如果有人能解釋我爲什麼我將不勝感激。

回答

5

這個想法是爲你的對象創建一個初始化中心點,而不是在每個初始化方法中分配變量的初始化。

您的特定示例對此模式沒有多大的公正性,因爲您正在初始化一個0寬度和0高度的Rectangle,默認情況下,默認的NSObject實現將所有實例變量的內存重置爲零,並且您的initWithWidth:andHeight:方法也一樣。然而,假設,你被默認分配單位矩形(寬度1,高度1)一個Rectangle對象是使用創建時,

[[Rectangle alloc] init] 

然後,而不是這樣做,

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

你通過只是在做初始化集中的點,

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

這也齊頭並進與DRY又名原則不重複自己。

這是一個微不足道的例子,但是,在大多數現實世界的對象中,您可能會有更復雜的設置,包括通知註冊,KVO註冊等等,然後您集中所有初始化邏輯。

+1

謝謝分配!爲什麼這些方法需要返回'id'類型?如果我知道什麼類型會叫他們..? @Anurag – MNY 2013-02-18 06:16:08

+0

保留返回類型'id'具有在子類化時自動轉換爲正確類型的靈活性,並且這種情況發生在編譯時,所以如果您嘗試調用實例方法,則會收到警告/錯誤在調用'alloc'的類中不存在的返回對象。希望我不會進一步混淆事物。但是,請記住,此編譯器僅檢查實例方法而不檢查類方法。 – Anurag 2013-02-18 06:25:29

+0

更好地使用實例類型,因爲當你使用'id'時,根本就沒有類型檢查。使用instancetype,編譯器和IDE知道返回什麼類型的東西,並且可以更好地檢查代碼並更好地自動完成。 – Bernard 2016-07-15 11:37:14

2

你沒有做。你通常有一個初始化函數調用super(self = [super initWithXX]),其他的則推遲到那一個。

在上面的具體示例中,它的一個好主意是因爲initWithWidth:andHeight充當主初始化器,所以如果您調用默認的代碼,那麼需要在主初始化器中運行的代碼將被調用。

順便說一句:在你的初始化參數中使用單詞'和'是現代Objective-C約定的一個陳舊的東西。