2013-02-18 68 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约定的一个陈旧的东西。