Is it safe to reinitialise self within a class method?
MyClass * a = [[MyClass alloc]init];
@implementation MyClass
{
-(id)init
{
if(self = [super init])
{
...
}
return self;
}
-(void)redefine
{
//??
self = [self init];
}
}
will a
point to the reinitialized开发者_开发问答 instance of MyClass?
Thank You, nonono
Provided that (a) your class and its superclasses can be re-init
'ed without leaking memory or resources and (b) you know that your class and its superclasses init
s all return the self
they are passed and not a reference to some other object, then yes...
Otherwise things will go wrong. Consider your redefine
method; in the body of this method self
is just a local variable whose contents is initialized to point to some object. Changing the value in that local variable does not change the object it originally pointed at, or the value of any other variables which point to that object. E.g. consider the variation:
@implementation Q
{
- (void) redefine
{
self = [[Q alloc] init]; // changes the *local* self to refer to a new object
}
...
}
...
Q *someQ = [[Q alloc] init]; // allocate an object
[someQ redefine]; // NO effect on someQ, another Q is just created and leaked
Clearly this does not alter someQ
, and your version may not either. Your code will have the effect you wish if and only if you know init
always returns the object it was passed - which is not guaranteed in Obj-C.
As long as init
returns self
, which it normally does, nothing will go wrong.
But you probably want to split your initialization to some separate method, which you can call from both init
and redefine
.
You need to return your new object from -init
, not simply assign a new value to self. And you must remember to release the old self, since it was created with +alloc
. Caveats aside though, returning a different object from -init
is explicitly allowed. That's why you'll see newbies being corrected when they write something like this:
// Bad example! Do NOT do this!
Foo *foo = [Foo alloc];
[foo init];
This is an anti-pattern because -init
is not required to return the same object it was called on. That means the above can end up assigning foo to point to an object that's been released, instead of to the object that was initialized in its place. This is why you always see +alloc
and `init
chained together like so:
Foo *foo = [[Foo alloc] init];
It's also why you need to reassign self when calling super's -init
, because it may also have returned a different object.
self = [super init];
精彩评论