Instance Initialization(初始化对象)
对象的初始化在Objective-C是个棘手的问题。需要先调用alloc这个类方法(从NSObject中继承的)给对象分配空间,然后再调用对象本身的实例方法去初始化对象中的所有实例变量。这个工作与C++和Java都有些不同。在Java中的构造函数是一个特殊的方法,它既不是类方法,也不是实例方法。实际上,即使你在类中没有实现一个初始化用的实例方法,你还是可以初始化一个对象的所有实例变量。如下的调用方法总是有效:
SomeComplexClass *c = [[SomeComplexClass alloc] init];
即使你在SomeComplexClass类中,并没有实现init这个方法,你也可以调用它,因为SomeComplexClass的父类也许实现了init方法,再或者,最极端的情况是SomeComplexClass的所有祖先类都没有实现init方法,但是NSObject类至少实现了init这个方法。但是显而易见的是,NSObject类的init方法不可能知道SomeComplexClass这个类的所有实例变量是什么,所以它提供的init方法明显不能完成初始化SomeComplexClass对象的工作。基于这个原因,你就总需要提供一个SomeComplexClass自己的初始化方法。我们回到下面这个问题。
典型情况下,一个类会提供多个带参数的初始化方法(initWith…)去初始化所有对象中的实例变量。也可以提供一些类方法(+new)去实现内存分配和初始化实例变量,这点类似于Java中的构造函数功能的方便类方法(convenience class methods)。实现这些功能的通常做法请参看如下代码:
+ new
{
Point *point;
// 注意这里的self指向Point这个类,而非对象!
point = [[self allocWithZone: NSDefaultMallocZone()] init];
return point;
}
+ newWithX: (float)x0 Y: (float)y0
{
Point *point;
point = [[self allocWithZone: NSDefaultMallocZone()] initWithX: x0 Y: y0];
return point;
}
+ point
{
Point *point;
//注意self指向Point这个类的对象!
point = [self new];
return AUTORELEASE(point);
}
+ pointWithX: (float)x0 Y: (float)y0
{
Point *point;
point = [self newWithX: x0 Y: y0];
return AUTORELEASE(point);
}
- init
{
return [self initWithX: 0.0 Y: 0.0];
}
//这是一个御用的初始化方法("designated" initializer)
- initWithX: (float)x0 Y: (float)y0
{
self = [super init];
if (self != nil)
{
x = x0;
y = y0;
}
return self;
}
首先,这个方便构造器(类似于Java中的构造函数)new and newWithX:Y:执行了[self allocWithZone: NSDefaultMallocZone()]。这时,这里的self指向的是Point这个类而不是对象,因为self调用了一个类方法allocWithZone,这个写法与在方法外面调用[Point alloc]是一个意思。
第二,注意一下另外的方便构造器(point and pointWithX:Y:),在返回一个对象之前,调用了autorelease方法将对象放进了autorelease pool中,这遵循了上一章节中关于内存管理方面的规则。
第三,注意一下,所有的new..开头的方法里面,都调用了init方法。其实不是必须这么去做,有new就要调用init方法,而只是一个方便构造器的编码习惯。
第四,注意这个语句[self allocWithZone: NSDefaultMallocZone()]不是必须这么写的,实际上这么写会稍微地让代码运行地更快一点,因为alloc方法实际上也是通过调用的+allocWithZone:来实现的。
{$ activeFileHint $}