把对象的分配和初始化进行合并
在Cocoa中,一些类中定义了把对象分配和初始化合并在一起的方法。这些方法通常被称为“便捷的的构造方法”。他们通常的形式为: +类名...。例如,NSString类就有这样的方法: +(id) stringWithCString:(const char *)cString encoding:(NSStringEncoding) enc;
+(id) stringWithFormat:(NString *)format, ...;
类似地,在NSArray类中定义了把分配对象和对其进行初始化合并在一起的方法:
+(id) array;
+(id) arrayWithObject:(id)anObject;
+(id) arrayWithObjects:(id)firstObj, ...;
重要:如果没有使用垃圾回收机制,那么使用这种方法的时候,我们必须明确知道此时的内存管理机制。更多信息请参阅《内存管理编程指南》一书。
这种便捷的构造方法的返回值是id,其中的原因和初始化方法的返回值为id是一样的,正如在“初始化方法相关的限制和惯例”小节中描述的那样。
这种把分配和初始化合并在一起的方法在实际中很有用,特别是当分配对象和初始化之间有着某种联系的时候。例如,当需要以文件中的数据来对对象进行初始化,而文件中可能含有多个对象的数据的时候,如果将分配对象和初始化操作分开,那么在初始化之前是不能知道需要分配多少个对象的。在这种情况下,我们可以实现方法listFormFile:。该方法接受文件名作为参数。它将打开文件计算需要分配的对象的数量,并创建一个足够大的列表类容纳这些新对象,然后根据文件中的数据来对新分配的对象进行初始化,最后返回该列表。
如果想要避免为新对象分配了后续可能不会被用到的空间的情况,把分配和初始化合并起来也是很意义的。正如我们在“init方法的返回值”一节中讨论的那样,init...方法可能返回的不是消息的接收者,而是别的对象。比如,如果向initWithName:方法被传入了一个已经在使用的名字,方法中可能会释放掉消息接收者对象,取而代之,返回的是先去被赋予改名字的对象。此时就出现了对象被分配后随即又被释放而没有得到使用的情况。
如果决定接收者是否应该被初始化的代码是被放置在为其分配空间的方法中而不是init...方法中,此时就可以避免前面提到的分配无用空间的情况。
在下面的示例中,soloist方法确保了只能生成一个Soloist类的对象。其中分配并初始化了一个共享的实例:
+(Solooist) soloist
{
static Soloist * instance = nil;
if ( instance == nil )
{
instance =[[self alloc] init];
}
return instance;
}
注意在上面的方法中,返回值的类型是Soloist *。因为这个类采用的是单实例模型,返回强类型是比较合适的。该方法不应该被重写。