我为什么不分开alloc和init?

时间:2015-02-16 09:06:54

标签: objective-c initialization allocation convention

在Objective-C中初始化和分配的常规方法是

NSObject *someObject = [[NSObject alloc] init];

为什么以下没有实践?

NSObject *someObject = [NSObject alloc];
[someObject init];

4 个答案:

答案 0 :(得分:9)

主要问题是你最终可能会使用错误的对象。

init在许多类中都很特殊,因为它可能只是释放接收器而是创建一个驻留在不同地址的新对象。所以你的someObject然后指向错误的(未初始化的)实例。

有很多框架类使用init方法的参数来决定哪种专用子类最好使用。对于像NSStringNSArray这样的类群集,这种情况经常发生,但每种对象都会发生这种情况。

您可以在其中看到初始化程序的这种特殊行为的地方是ARC:It explicitly declares that the init family of methods eats up the receiver and returns a +1 retained object。如果初始化器只是总是返回接收器,则不需要这样做。

当然,您可以通过执行另一项任务来修复您的代码:

NSObject *someObject = [NSObject alloc];
someObject = [someObject init];

这可以解决问题。但这样做也没有任何意义。

答案 1 :(得分:4)

来自对象初始化官方documentation

  

因为init ...方法可能返回nil或除了显式分配的对象之外的对象,所以使用alloc或allocWithZone返回的实例是危险的:而不是初始化程序返回的实例

同一文件的另一个原因是:

  

初始化对象后,不应再次初始化

给出了这个例子:

NSString *aStr = [[NSString alloc] initWithString:@"Foo"];
aStr = [aStr initWithString:@"Bar"];

其中:

  

此示例中的第二个初始化将导致引发NSInvalidArgumentException。

答案 2 :(得分:1)

因为它不那么简单,而且更容易出错。

分配但未初始化的对象是无用的,因此将分配和初始化放在一行中是有意义的。如果它们是分开的,如果两条线不是直接相继(可能在重构之后),则更有可能出现错误和错误,这可能会在尝试使用未初始化的对象时导致错误。

allocinit在单独的行中没有一个合理的理由,反对它的原因很多。

答案 3 :(得分:0)

根据我的理解,如果没有初始化分配的对象是没有意义的,

如果您首先alloc一个对象然后计划初始化它,可能会有一种情况,您可能忘记初始化该对象并直接调用它的任何实例方法,这将导致运行时间错误。

示例:

    NSString *str = [NSString alloc];
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
NSLog(@"%ld",str.length);

当我运行上面的代码时,我在我的控制台中得到了这个

Did you forget to nest alloc and init?
 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '*** -length only defined for abstract class.  Define -[NSPlaceholderString length]!'

如果我会这样做,我仍然会得到异常,因为str没有被初始化,因为正在初始化的内容没有被str消耗或指向

[str init];

因此,如果你想在两行中完成它应该是这样的

NSObject *someObject = [NSObject alloc];
someObject = [someObject init];

但保持嵌套

总是更好
NSObject *someObject = [[NSObject alloc]init];

如果您计划在单行上执行此操作,请使用new关键字,该关键字用于在一行上分配和初始化的目的。

示例: YourClass *object_ofClass = [YourClass new];