How to call a grandparent method
i need to call a grandparent method of my class.
@class Grandparent
+--->@class Parent
+---->@class Child
Every class implement a method:
-(void)foo
If i wan开发者_Go百科t to call the parent method foo from child class i use:
[super foo]
If i want to call grandparent's foo, how can i do? It's not possible to call
[super [super foo]]
Ant ideas?
You can, of course, accomplish this with the help of the parent class. If your foo
calls [super foo]
and your superclass then in turn calls [super foo]
because it expects this behavior, then you're all set. This is a common pattern (e.g. -init
and -dealloc
).
But you can't jump directly using normal Obj-C syntax. Every subclass defines its own set of semantics for a class around its state and methods. If you could arbitrarily call implementations anywhere up your inheritance chain without the intermediate implementations knowing anything about it, then no implementation would have any guarantees about the integrity of its own state, and it would break the abstractions around classes.
In other words, and I hate being the guy that says this, you should rethink your design if this seems to be what you really want to do. (If so, feel free to open a new question to discuss the design of your object model. People here will be happy to assist.)
That said, technically, I suspect you can accomplish this by dealing directly with the Obj-C runtime. You can get your object's class reference, then its superclass, then its superclass, and get the method implementation you want from it. Then call it with your object. Code for this is an exercise for the reader. :) Here are the docs.
If you feel like you need to do this, it's probably a bad design. You should rethink what you're doing along the lines of quixoto's answer. quixoto mentioned the objective c runtime library, but NSObject has instance and class side methods to do that stuff. Like quixoto, I'll leave this as an exercise for you. The methods to look at are -(Class)class
, +(Class)superclass
, +(IMP)instanceMethodForSelector:SEL
and you'll need to read the section about the SEL
and IMP
types and how to call methods through IMP
s.
If you write the code and it looks awful (it will, don't worry), it's probably because you're not supposed to do it.
if you really wanted to do this (not totally sure why), you would rig the Parent to call the GrandParent ([super foo]). Then when the Child Foo calls the Parent Foo, it would call the GrandParent Foo.
optionally, you could just create a method on the parent that called [super foo].
Not sure why you want such a thing as it breaks OO design, but it sounded fun. Here's the working code for it:
#import <objc/message.h>
...
- (void)foo {
struct objc_super x = {
self,
[[self superclass] superclass] // or any class compatible with self; repeat for more fun :)
};
objc_msgSendSuper(&x, @selector(foo));
}
When you're on the iPhone, you'll see a design pattern like this:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
if you create a new sub-class of UIViewController. As others have suggested, you should follow this pattern when overloading methods in sub-classes.
@implementation Grandparent
- (void) printSelf
{
NSLog(@"Grandparent");
}
@end
@implementation Parent
- (void) printSelf
{
[super printSelf];
NSLog(@"Parent");
}
@end
@implementation Child
- (void) printSelf
{
[super printSelf];
NSLog(@"Child");
}
@end
I don't think you can do the following, because method calls are determined at run-time, not compile-time. This would probably work for Java or C++ though, because of the binding and dispatch rules of the languages.
@implementation Child
- (void) printSelf
{
[(Grandparent *)self printSelf]
}
@end
Try it, but I doubt it will work.
精彩评论