[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Class clusters: MacOSX/GNUstep differences?
From: |
Richard Frith-Macdonald |
Subject: |
Re: Class clusters: MacOSX/GNUstep differences? |
Date: |
Wed, 1 Sep 2004 16:49:04 +0100 |
On 1 Sep 2004, at 15:53, Ronan Collobert wrote:
Hello,
I have to implement a true subclass of the NSArray class. My code
works
well under MacOS X, but does a "seg fault" under GNUstep.
After looking at the code of NSArray.m and GSArray.m, I found that in
GNUstep, if we want to implement a subclass of NSArray we have to
derive
not only the standard two primitives count: and objectAtIndex:
but also
- (id) initWithObjects: (id*)objects count: (unsigned)count;
Indeed, in NSArray.m, the init method is implemented as
- (id) init
{
return [self initWithObjects: (id*)0 count: 0];
}
and initWithObjects: as
- (id) initWithObjects: (id*)objects count: (unsigned)count
{
[self subclassResponsibility: _cmd];
return nil;
}
I understand that if we define initWithObjects: in a subclass, then
it's
cool because all other init methods of NSArray will work well in the
subclass. However, we are *forced* to declare this method in the
subclasses with GNUstep, which is not (to my opinion) what is
specified in
the Cocoa framework. Here is a cut and paste of a discussion on class
clusters by apple:
(see
http://developer.apple.com/documentation/Cocoa/Conceptual/Foundation/
Concepts/ClassClusters.html)
"Your subclass should declare its own init... [...] It should not
rely on any of those that it inherits. To maintain its link in the
initialization chain, it should invoke its superclass's designated
initializer within its own designated initializer method. Within a
class
cluster, the designated initializer of the abstract superclass is
always
init"
Note that in the NextStep3.3 specifications, there is exactly the same
text.
(see
http://www.channelu.com/NeXT/NeXTStep/3.3/nd/Foundation/
IntroFoundation.htmld/index.html)
Interesting, I never saw the EOF documentation.
And I never saw in the Apple/NextStep documentation that
initWithObjects:
has to be considered as a primitive method.
Maybe the OpenStep specifications are different, but the document
provided
on www.gnustep.org seems not to talk about this particular point.
I'm pretty certain that the OpenStep specification did not say this ...
because at
some point when working on class clusters I wanted a clear policy on
initialisation
and couldn't find anything in the spec ... though I do remember finding
something
saying that a subclass needed to override the superclass initialisers
in order to
prevent those initialisers returning instances of other classes.
I therefore adopted the policy that class clusters should, like any
other class,
have designated initialisers. Also that, like other classes, the
designated
initialiser should be the 'richest' initialiser. So that, in GNUstep
it should be
possible to override a single designated initialiser and have all the
other
initialisers work as expected, ie to improve on the OpenStep spec
That's why the GNUstep class documentation specifies the designated
initialiser
of NSArray to be initWithObjects:count:
Anyways, it is quite annoying, because I cannot have the full
compatibility between MacOS X and GNUstep. Even if I declare this
initWithObjects: method in my code, in MacOS X I should have a line
such as
[super init]
according to what apple says, which will cause an infinite loop under
GNUstep.
Maybe this has been already discussed in the past, but I didn't find
anything in the mailing list archives. Any comments on this?
I know class cluster iniitialisation was discussed in the past ... but
it
was years ago and may have been in a private mailing list back then.
I think the GNUstep behavior is superior in that it makes initialisers
reliably available so that creators of subclasses don't need to override
them all, and it makes the behavior of class clusters consistent with
that of other classes ... but I sympathise with the portability problem.
I'm reluctant to make things harder for GNUstep coders by forcing
them to implement initialisers that the abstract class ought to handle,
but I can't immediately see an elegant portability solution.
The obvious inelegant one is -
- (id) initWithObjects: (id*)o count: (unsigned)c
{
#ifdef MACOSX
if ((self = [super init]) == nil)
{
return nil;
}
#endif
// Your initialisation here
return self;
}