FROM : Wade Tregaskis
DATE : Sun Feb 10 20:50:58 2008
> As i get ready to teach non-cocoa programmers in my company about
> cocoa programming, and having read Will Shipley's blog, Is the
> above the way to teach writing an initializer? I see Will, and a
> few others, say no [super init] will initialize self in its code
> there is no reason to assign self. Yet all code and docs I see have
> similar code.
Initialisers do not have to - and often don't - return self. They
are free to release self and return nil, or a different object, which
can even be a different class (though it's considered rather poor
form to return an object which isn't at least an instance or subclass
of the class who's initialiser is doing this magic).
It's important to recognise that, if init fails, you're supposed to
call [self release] and return nil, because typical code is:
> MyClass *woot = [[MyClass alloc] init];
If you just return nil without releasing, you've just leaked
yourself. So, ultimately the test for nil from [super init] is very
often necessary, and is a good coding style. Good coding style in
the sense that it will prevent your program from crashing.
Now, since we're all here already, and you've gotten me started, you
must endure all of it. :P So, truth be told, if you have a hierarchy:
A -> B
A -> C
A's initialiser, when called by say B, could hypothetically release
self, allocate an object of class C, and return that. If you want to
be really defensive in your coding, you could write:
> self = [super init];
>
> if ((nil != self) && [self isKindOfClass:[MyClass class]]) {
> ...
> }
>
> return self;
I've never seen anyone actually write that, though. Typically your
initialiser will return either nil, or an object of the same lineage
(or a further subclass thereof) of the original object. When you
start considering scenarios like {A, B, C} above, things can get
pretty silly very quickly. And generally when people start doing
things like this, it's because they've decided that transparent class
clusters would be really cool, and I always wonder if such dubious
practices are wise anyway... the official Apple line in such cases,
anyway, is don't subclass class clusters, so if you take that as
gospel this is a moot point.
And as Wil points out (http://www.wilshipley.com/blog/2005/07/self-
stupid-init.html) if your superclass' initialiser is funky because it
returns singletons (or similar) - which is the most common case of
this sort of thing - then you have issues with re-initialising
existing instances (which if nothing else will leak, because
virtually no-one releases/frees existing ivars in their
initialisers). So you'd have to then write:
> id newSelf = [super init];
>
> if (self == newSelf) {
> ...
> } else {
> [self release];
> self = newSelf;
> }
>
> return self;
However, that's assuming super always returns either self or an
existing, fully-initialised instance, which as noted previously
doesn't have to be the case...
Generally, protecting against nil should be quite sufficient, as
noted, and in the few cases where a class does do funky voodoo in its
initialisers, it should document as such and explain exactly what it
could hypothetically do, so you can write your subclasses appropriately.
[[ pre-emptive retort: some people argue that you shouldn't worry
about initialisers returning nil because that means you're out of
memory and your program is hosed anyway... this is complete crap -
even aside from the fact that an initialiser returning nil could mean
any of numerous things - and many programs are designed to - and will
quite successfully - recover from such situations... iff they have
proper checks in place and don't dereference NULL immediately ]]
Wade
DATE : Sun Feb 10 20:50:58 2008
> As i get ready to teach non-cocoa programmers in my company about
> cocoa programming, and having read Will Shipley's blog, Is the
> above the way to teach writing an initializer? I see Will, and a
> few others, say no [super init] will initialize self in its code
> there is no reason to assign self. Yet all code and docs I see have
> similar code.
Initialisers do not have to - and often don't - return self. They
are free to release self and return nil, or a different object, which
can even be a different class (though it's considered rather poor
form to return an object which isn't at least an instance or subclass
of the class who's initialiser is doing this magic).
It's important to recognise that, if init fails, you're supposed to
call [self release] and return nil, because typical code is:
> MyClass *woot = [[MyClass alloc] init];
If you just return nil without releasing, you've just leaked
yourself. So, ultimately the test for nil from [super init] is very
often necessary, and is a good coding style. Good coding style in
the sense that it will prevent your program from crashing.
Now, since we're all here already, and you've gotten me started, you
must endure all of it. :P So, truth be told, if you have a hierarchy:
A -> B
A -> C
A's initialiser, when called by say B, could hypothetically release
self, allocate an object of class C, and return that. If you want to
be really defensive in your coding, you could write:
> self = [super init];
>
> if ((nil != self) && [self isKindOfClass:[MyClass class]]) {
> ...
> }
>
> return self;
I've never seen anyone actually write that, though. Typically your
initialiser will return either nil, or an object of the same lineage
(or a further subclass thereof) of the original object. When you
start considering scenarios like {A, B, C} above, things can get
pretty silly very quickly. And generally when people start doing
things like this, it's because they've decided that transparent class
clusters would be really cool, and I always wonder if such dubious
practices are wise anyway... the official Apple line in such cases,
anyway, is don't subclass class clusters, so if you take that as
gospel this is a moot point.
And as Wil points out (http://www.wilshipley.com/blog/2005/07/self-
stupid-init.html) if your superclass' initialiser is funky because it
returns singletons (or similar) - which is the most common case of
this sort of thing - then you have issues with re-initialising
existing instances (which if nothing else will leak, because
virtually no-one releases/frees existing ivars in their
initialisers). So you'd have to then write:
> id newSelf = [super init];
>
> if (self == newSelf) {
> ...
> } else {
> [self release];
> self = newSelf;
> }
>
> return self;
However, that's assuming super always returns either self or an
existing, fully-initialised instance, which as noted previously
doesn't have to be the case...
Generally, protecting against nil should be quite sufficient, as
noted, and in the few cases where a class does do funky voodoo in its
initialisers, it should document as such and explain exactly what it
could hypothetically do, so you can write your subclasses appropriately.
[[ pre-emptive retort: some people argue that you shouldn't worry
about initialisers returning nil because that means you're out of
memory and your program is hosed anyway... this is complete crap -
even aside from the fact that an initialiser returning nil could mean
any of numerous things - and many programs are designed to - and will
quite successfully - recover from such situations... iff they have
proper checks in place and don't dereference NULL immediately ]]
Wade
| Related mails | Author | Date |
|---|---|---|
| Scott Andrew | Feb 10, 18:18 | |
| Scott Andrew | Feb 10, 18:35 | |
| Adhamh Findlay | Feb 10, 19:41 | |
| John Newlin | Feb 10, 20:13 | |
| Hans van der Meer | Feb 10, 20:20 | |
| Quincey Morris | Feb 10, 20:29 | |
| Jens Alfke | Feb 10, 20:45 | |
| Wade Tregaskis | Feb 10, 20:50 | |
| Ricky Sharp | Feb 10, 21:01 | |
| Jens Alfke | Feb 10, 22:44 | |
| Hans van der Meer | Feb 10, 23:26 | |
| Paul Bruneau | Feb 10, 23:29 | |
| Uli Kusterer | Feb 10, 23:40 | |
| Paul Bruneau | Feb 11, 00:18 | |
| Scott Andrew | Feb 11, 00:56 | |
| Quincey Morris | Feb 11, 02:32 | |
| mmalc crawford | Feb 11, 02:49 | |
| Jens Alfke | Feb 11, 03:05 | |
| Bill Bumgarner | Feb 11, 03:28 | |
| Quincey Morris | Feb 11, 04:35 | |
| Jean-Daniel Dupas | Feb 11, 10:27 | |
| Jens Alfke | Feb 11, 17:08 | |
| Ben Trumbull | Feb 11, 23:58 |






Cocoa mail archive

