Larry Campbell schrieb:
On Jan 21, 2006, at 4:50 AM, David Ayers wrote:
Have a look at this discussion:
http://lists.apple.com/archives/objc-language/2004/Mar/msg00006.html
Now, I'm no advocate of being different just for the sake of being
different, but I also think that '+load' and '+initialize' are simply
"special" wrt inheritance and guarantees on how/when they are called and
I would assume that we would break code written for the FSF libobjc
runtime if FSF's libobjc started to inherit +initialize.
However, I think that:
1. The difference between FSF here and Apple is a trap for the unwary
2. It would be best to remove such traps when possible
3. Due to binary compatibility it's extremely unlikely Apple will change
4. There's no clear advantage to the FSF approach (or the Apple approach)
All of these points could be applied for most of the FSF libobjc API.
(E.g., did you know that the class pointer of an 'id' in FSF's libobjc
is called 'class_pointer' instead of 'isa'? But yes, I realize the
inconsistency that Object.h still uses 'isa' as the ivar name.)
The reasons are historical and I assume have to do with the reluctance
of NeXT to release their GCC modifications to ObjC in the first place.
I kind of doubt that the FSF wanted to make their libobjc incompatible,
but I don't know the details of what happened and they seem to diverge
quite a bit more than I would have expected... Anyway, now there is
code out there that relies on FSF's libobjc and we should consider
changes carefully.
5. If you really want to share initialization code with subclasses, you
have to move such initialization code into a separate method, or
subclasses have to call [super initialize]
Moving them to separate methods that get invoked by +initialize seems
like the most robust approach to me.
So I think I would argue that FSF should consider changing; not
precipitously, and with perhaps a way to override via an environment
variable in case of compatibility bugs.
Well this is the type of discussion that the above mentioned list was
created for. I am personally undecided on the issue and would insure
that any code I write today would be portable. Even if it is decided to
change the GNU semantics I believe the earliest libobjc release would be
4.2 (or possibly 4.3 depending on libobjc maintainers view this in light
of the pending switch to Stage 2 of gcc's trunk) and any code relying on
NeXT/Apple semantics would have to wait until that compiler version is
in wide spread use.
Note that if you actually invoked either +initialize or +load in a true
method invocation, the normal inheritance techniques would be used. But
be warned, code often is not prepared for multiple invocations of these
methods and could break in strange ways (e.g. replacing objects/caches
which were meant to be initialized as singletons).
Yes, sadly all my initialize methods now have to look like this:
+ (void)initialize
{
if (self == [MyClass class]) {
static BOOL inited = NO;
if (!inited) {
// do stuff
}
}
}
(This still doesn't help with category initialize, but I try to avoid
categories and I've never tried category initialize)
Category +initialize is a different story all together. Please read
that thread closely and then maybe you can propose semantics that we can
be discussed on that list.
- Should a category be able to replace the +initialize implementation of
a class?
- Should it be sent if the category is loaded after the first method
(and therefor the initial +initialize invocation has already been executed)?
- Should it only be sent on the first invocation of any method that the
particular category implements rather than any method the class implements?
- What is the expected hit on standard runtime method invocations if you
have to do all that checking during method dispatch?
When I went through all of that, I decided that +initialize on a per
category basis can not give the guarantees I would like and stay
efficient at the same time. But maybe you have some new ideas.
Cheers,
David