Re: superclass and awakeFromNib
Re: superclass and awakeFromNib
- Subject: Re: superclass and awakeFromNib
- From: Daniel Zitter <email@hidden>
- Date: Tue, 17 Dec 2002 13:07:44 -0800
I think there are some ways to work around this if you are willing to
get your hands a little dirty. This function walks the ancestral path
and return YES if any ancestor of class responds to selector:
BOOL shouldCallSuper (Class class, SEL selector)
{
NSCAssert(selector, @"unable to determine if should call super:
selector is 0");
NSCAssert(class, @"unable to determine if should call super: class
is nil");
for (class = [class superclass]; class; class = [class superclass])
{
if ([class instancesRespondToSelector:selector]) {
return YES;
}
}
return NO;
}
So, for a particular class, say MyClass, one could write
- (void)awakeFromNib;
{
if (shouldCallSuper([MyClass class], _cmd)) {
[super awakeFromNib];
}
}
This is bit much, but it works. Since many class files are named after
my classes, one may leverage the __FILE__ macro with this function:
BOOL shouldCallSuperForClassWithFilename (char *filename, SEL selector)
{
NSCAssert(filename, @"unable to determine if should call super:
filename is NULL");
NSCAssert(selector, @"unable to determine if should call super:
selector is 0");
NSString *classname = [[[NSString stringWithCString:filename]
lastPathComponent] stringByDeletingPathExtension];
NSCAssert(classname, @"unable to determine if should call super:
class name is NULL");
Class class = NSClassFromString(classname);
NSCAssert1(class, @"unable to determine if should call super: class
named %@ not found", classname);
return shouldCallSuper(class, selector);
}
(Wouldn't a __CLASS__ macro be classy?)
For extra sprinkles on top, define a macro to sew this all up:
#define SUPER_AWAKEFROMNIB \
if (shouldCallSuperForClassWithFilename(__FILE__, _cmd)) { \
[super awakeFromNib]; \
}
leaving the implementation of awakeFromNib lean and mean
- (void)awakeFromNib;
{
SUPER_AWAKEFROMNIB;
// do the rest
}
If anyone sees holes in this I'd appreciate the feedback.
Cheers,
--Dan
Message: 12
Date: Tue, 17 Dec 2002 09:20:14 -0800
From: matt neuburg <email@hidden>
Subject: Re: superclass and awakeFromNib
To: email@hidden
Date: Sat, 14 Dec 2002 07:48:59 -0800
From: matt neuburg <email@hidden>
Subject: Re: superclass and awakeFromNib
To: email@hidden
So my question is: *is* there a general incantation that can be put
at the
start of every awakeFromNib to ensure etc. etc. etc.? Yes, I know I
can
consult the runtime, my own code, and so on, and just call [super
awakeFromNib] if the superclass has an awakeFromNib implementation
and not
call it if it doesn't; but that's a huge pain, especially when your
code
has subclasses its own classes a lot. I'd like the computer to do the
work, not me
What the problem boils down to is that there is an asymmetry between
the way "self" works and the way "super" works. This is well
illustrated in Apple's excellent docs on Objective-C. To paraphrase
the example given there, suppose we have three classes: High, its
subclass Middle, and *its* subclass Low. Suppose Middle implements
"callSayHello", and all three classes implement "sayHello". Now, make
an instance of Low and send it the "callSayHello" message. Remember,
"callSayHello" is implemented in Middle only, but our instance is a
Low.
If "callSayHello" goes:
[self sayHello]
then it is Low's "sayHello" that is called. Why? Because "self" means
that message resolution starts with the class of the instance that
received the message that started this whole thing. That's Low,
because we originally created an instance of Low.
If "callSayHello" goes:
[super sayHello]
then it is High's "sayHello" that is called. Why? Because "super"
means to look up the hierarchy for an implementation, starting just
above the class that is running the code right now. Since Middle is
running the code (because "callSayHello" is implemented only in
Middle), that's High.
Apple's docs point out that this means "callSayHello" can't call
Middle's "sayHello". That is a practical consequence of a more
fundamental functionality hole - there is no way to refer to "the
class that is actually running this code right this very moment".
That is why no universal awakeFromNib handler can be simply written;
there's no way to know whether the superclass of the class that's
running this code implements awakeFromNib because there's no way to
know what class is running this code. The class that originally
receives the awakeFromNib message will get it right, of course,
because it is "self", and can be sent the "superclass" message; but
when it invokes its superclass's awakeFromNib, *that* class can't find
out whether *its* superclass implements awakeFromNib because it can't
find out what class that is and can't ask any questions about it. m.
matt neuburg, phd = email@hidden, http://www.tidbits.com/matt
pantes anthropoi tou eidenai oregontai phusei
Subscribe to TidBITS! It's free and smart. http://www.tidbits.com/
--__--__--
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.