Re: semantics of init
Re: semantics of init
- Subject: Re: semantics of init
- From: Wade Tregaskis <email@hidden>
- Date: Wed, 4 Jun 2003 13:41:55 +1000
Okay, so I'm quite new to Obj. C, but I'm wondering the following.
I read somewhere that the following code is dangerous, generally
speaking:
id obj = [SomeClass alloc];
[obj init];
The manual I was reading said that 'init' may return a different value
other
than self if it wants to, so to be safe, you should do:
id obj = [[SomeClass alloc] init];
The reason you should use the second form is that if SomeClass is just
the tip of a class cluster, init will sometimes (and for some clusters,
always) return a different instance, being one of the classes within
the cluster. If you use the first form, your original object will be
released by the init method, so you'll have a dangling pointer, and the
new instance will be returned but ignored, so you'll also have a memory
leak.
Okay, that seems fine. However, I'm wondering when you extend some
class,
are you supposed to respect that rule in your own init functions?
Yes.
For example, suppose I extend SomeClass with SomeOtherClass, should I
do something like this in the constructor?
<snip>
This seems stupid and annoying. I'm assuming that nobody in their
right mind would do anything but return 'self' from init, or if they
did so it would be well-documented and for some no doubt very worthy
cause, so I shouldn't worry about it. I'm wondering, though, if there
is
some nice way to both be safe and not have to write annoying code like
my
first example.
Your assumption that no-one would return anything other than self is
simply wrong. I'd dare say a sizable fraction of the Foundation
classes return objects other than themselves. And a lot of third party
developers make use of this (to the point of abuse) in their coding.
As a concrete example, I have my own generic superclass called
NSCachedObject, which allows me to only ever create one instance for a
particular piece of data. Any attempts to init another instance with
the same data will instead return the existing instance. So quite
often the user *must* respect the fact that init can return a different
instance. If they don't, they'll end up with a lot of dangling
pointers and no functionality.
The simplest and most 'standard' way to do all this is to observe the
following rules:
1) Don't separate alloc and init calls. It's generally considered just
poor form. Plus it might (i.e. I haven't checked) prevent the compiler
from optimizing it's memory allocation and stuff
2) If you do call init at another place, make sure to say "myRef =
[myRef init]" to overcome the problems discussed
3) If you're defining a subclass, always do the following, in one form
or another:
- (mySubClass)init {
if (self = [super init]) {
// initialize your subclass here
}
return self;
}
I even do the above in direct subclasses of NSObject, even though so
far as I know [NSObject's init method doesn't do anything. The point
is that, some time in the future, it might. Or, I might change the
superclass for my subclass. Then I'd have to go changing my subclasses
init method, if I didn't already call [super init].
Wade Tregaskis
-- Sed quis custodiet ipsos custodes?
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.