discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Why is +initialize not inherited?


From: Fred Kiefer
Subject: Re: Why is +initialize not inherited?
Date: Thu, 15 Sep 2011 18:01:08 +0200
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.22) Gecko/20110907 SUSE/3.1.14 Thunderbird/3.1.14

I have to apologize, sticking to these simple rules isn't as easy as I thought it would be. I just fixed a bug in Gorm that was inside of an +initialize method in a category. Just imagine somebody had implemented that method in the main class later on.

On 14.09.2011 23:39, Fred Kiefer wrote:
What exactly was the problem that you experienced?
In GNUstep we always write our +initialize methods like this and I don't
know of any problem with that style:

+ (void)initialize
{
if (self == [MyClass class])
{
// do stuff
}
}

There are certain differences between the different runtimes, but in
most cases you are save to ignore them as long as you stick to a careful
coding style.

On 14.09.2011 23:09, Larry Campbell wrote:
Today, having forgotten this five-year-old conversation, I was burned
by this again.

I cannot think of any good reason (other than inertia) for +initialize
not to be inherited as it is on Mac OS X. It's incompatibilities like
this that make it hard to recommend Objective-C. Does anyone else care
about this?

- lc


On Jan 21, 2006, at 1:31 PM, David Ayers wrote:

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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]