Why should I not separate alloc and init?

老子叫甜甜 提交于 2019-12-20 03:31:33

问题


The normal way to initialise and allocate in Objective-C is

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

Why is the following not practised?

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

回答1:


The main problem is that you might end up using the wrong object.

init is special in many classes as it might just release the receiver and instead create a new object that resides at a different address. So your someObject then points to the wrong (uninitialized) instance.

There are a lot of framework classes that use the arguments of the init method to decide which kind of specialized subclass is best to use. This frequently happens with class clusters like NSString or NSArray but it can really happen with each kind of object.

One place where you can see this special behavior of initializers is ARC: It explicitly declares that the init family of methods eats up the receiver and returns a +1 retained object. This would not be necessary if initializers would just always return the receiver.

Of course you could fix your code by just doing another assignment:

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

This would fix the problem. But there's also no sense in doing it.




回答2:


From the Object Initialization official documentation:

Because an init... method might return nil or an object other than the one explicitly allocated, it is dangerous to use the instance returned by alloc or allocWithZone: instead of the one returned by the initializer

Another reason from the same document is that:

Once an object is initialized, you should not initialize it again

given this example:

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

where:

the second initialization in this example would result in NSInvalidArgumentException being raised.




回答3:


Because it is less simple and more error-prone.

An allocated but not initialised object is useless, so it make sense to put allocation and initialisation in one line. If they are separated, there is more possibility for errors and bugs if the two lines are not directly after each other (perhaps after refactoring), which may lead to errors while trying to use an uninitialised object.

There simply isn't a single good reason to alloc and init in separate lines, and many reasons against it.




回答4:


As per my understanding an allocated object makes no sense without it being initialized,

if you alloc an object first and then later plan to initialize it, there might be a case that you may forget to initialize the object and give a direct call to any of its instance method which would result in run time error.

Example:

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

When i run the above code i get this in my console

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]!'

if i would do the below I would still get the exception as str is not being initialized because whatever is being initialized is not being consumed or pointed by str

[str init];

Hence if you want to do it in two lines it should be like this

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

But it's always better to keep them nested

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

If you plan on doing it on single line then use the new keyword which servers the purpose of allocation and initialization on a single line.

Example: YourClass *object_ofClass = [YourClass new];



来源:https://stackoverflow.com/questions/28537853/why-should-i-not-separate-alloc-and-init

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!