On Feb 11, 2010, at 10:28 PM, Graham Cox wrote:

> On 12/02/2010, at 1:43 PM, Gordon Apple wrote:
> 
>> My point was that if all Cocoa classes called "init"
>> somewhere in their other initializers (or had a two-step initialization
>> similar to what MacApp did), then you could simply override (not call)
>> "init" for simple ivar initialization in a subclass, which would in no way
>> interfere with a designated initializer.
> 
> 
> Except that it would be all too easy to create an infinite loop. A subclass 
> might implement -init to call super's designated initializer, which later 
> calls -init.
> 
> I'm not sure what's complex about overriding the designated initializer - 
> even if it has a complex set of parameters, (and most do not) then all you do 
> is pass them up to super. Your suggestion would only save a tiny, tiny amount 
> of work yet lead to potentially big problems.
> 
> --Graham

Not really; suppose you want to subclass some class that has two separate init 
methods:

- (id)initWithFoo:(Foo *)foo;
- (id)initWithBar:(Bar *)bar;

and suppose you just want to set some initial internal state, which needs to 
always be set the same way at init time no matter how the object is 
initialized. Which init method do you override? It’s possible that the 
“initWithFoo:” method may look like this:

- (id)initWithFoo:(Foo *)foo
{
        return [self initWithBar:[SomeClass convertAFooToABarSomehow:foo]];
}

in which case you’d just need to override initWithBar:. However, what happens 
if it’s actually the other way around, and initWithBar: looks like this:

- (id)initWithBar:(Bar *)bar
{
        return [self initWithFoo:[SomeClass convertABarToAFooSomehow:bar]];
}

Knowing which is which requires you to have knowledge of the parent object’s 
code. And what if the implementation of the parent changes over time from one 
of the above scenarios to the other? Clearly the only way to make sure your 
init *always* gets called is to override init, initWithFoo:, *and* 
initWithBar:, and if there are more than just two initializers, this can get 
quite cumbersome. And even then, what happens if the superclass gets updated so 
that a third initializer gets added:

- (id)initWithBaz:(Baz *)baz;

which doesn’t happen to call initWithFoo: *or* initWithBar:? Now your custom 
init won’t get called at all if that initializer is used.

Incidentally, there is just such a class in Cocoa: NSDocument. It provides six 
different init methods:

- (id)init;
- (id)initForURL:(NSURL *)absoluteDocumentURL withContentsOfURL:(NSURL 
*)absoluteDocumentContentsURLofType:(NSString *)typeName error:(NSError 
**)outError;
- (id)initWithContentsOfURL:(NSURL *)absoluteURL ofType:(NSString *)typeName 
error:(NSError **)outError;
- (id)initWithType:(NSString *)typeName error:(NSError **)outError;
- (id)initWithContentsOfFile:(NSString *)fileName ofType:(NSString *)docType;
- (id)initWithContentsOfURL:(NSURL *)aURL ofType:(NSString *)docType;

Yes, the last two of these are deprecated, but it’s still possible that they 
could get called, so you’d still have to take that into account. Interestingly, 
though, someone at Apple appears to agree with Gordon here, since all of those 
NSDocument initializers actually seem to call -[self init] instead of -[super 
init], with the result that you can in fact just override -init instead of 
having to override all six methods separately (and the NSDocument subclass 
template even includes an -init method, to further encourage this).

Charles_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to