サブクラスのインスタンスからポリモーフィズムを無視して任意のスーパークラスのメソッドを呼びます。
↓ 下のように Shape クラスと Shape クラスを継承した Path クラス、および Path クラス を継承した Circle があります。
それぞれのクラスで draw メソッドをオーバーライドしています。
//////////////////////////////////////////////////////////////////////// #pragma mark - Shape //////////////////////////////////////////////////////////////////////// @interface Shape : NSObject @end @implementation Shape - (void)draw { NSLog(@"%@", @"Shape."); } @end //////////////////////////////////////////////////////////////////////// #pragma mark - Path //////////////////////////////////////////////////////////////////////// @interface Path : Shape @end @implementation Path - (void)draw { NSLog(@"%@", @"Path."); } @end //////////////////////////////////////////////////////////////////////// #pragma mark - Circle //////////////////////////////////////////////////////////////////////// @interface Circle : Path @end @implementation Circle - (void)draw { NSLog(@"%@", @"Circle."); } @end
↓ Circle クラスのインスタンスから draw メソッドを呼び出すと Circle クラスの draw メソッドが実行されて "Circle." と出力されます。
たまに多態性を無視してスーパークラスや、スーパークラスのさらにスーパークラスのメソッドを実行したいということってありますよね。
そういうときは 対象メソッドの IMP (メソッドを参照する関数へのポインタ) を使います。
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Shape *shape = [[Circle alloc] init]; [shape draw]; // => Circle. SEL selector = @selector(draw); void(*pathFunction)(id, SEL, ...) = (void(*)(id, SEL, ...))[Path instanceMethodForSelector:selector]; pathFunction(shape, selector); // => Path. void(*shapeFunction)(id, SEL, ...) = (void(*)(id, SEL, ...))[Shape instanceMethodForSelector:selector]; shapeFunction(shape, selector); // => Shape. } @end
↑ IMP の定義のままだと ARC が戻り値を retain しようとするので、戻り値が void の関数ポインタにキャストしています。
↓ 上記のコードの出力は下記になります。
2012-10-23 13:15:20.632 Monomorphism[50033:c07] Circle. 2012-10-23 13:15:20.633 Monomorphism[50033:c07] Path. 2012-10-23 13:15:20.633 Monomorphism[50033:c07] Shape.
サブクラスのインスタンスからポリモーフィズムを無視して任意のスーパークラスのメソッドが呼べました。
↓ 試したコードの全体を載せておきます。
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @end //////////////////////////////////////////////////////////////////////// #pragma mark - Shape //////////////////////////////////////////////////////////////////////// @interface Shape : NSObject @end @implementation Shape - (void)draw { NSLog(@"%@", @"Shape."); } @end //////////////////////////////////////////////////////////////////////// #pragma mark - Path //////////////////////////////////////////////////////////////////////// @interface Path : Shape @end @implementation Path - (void)draw { NSLog(@"%@", @"Path."); } @end //////////////////////////////////////////////////////////////////////// #pragma mark - Circle //////////////////////////////////////////////////////////////////////// @interface Circle : Path @end @implementation Circle - (void)draw { NSLog(@"%@", @"Circle."); } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Shape *shape = [[Circle alloc] init]; [shape draw]; // => Circle. SEL selector = @selector(draw); void(*pathFunction)(id, SEL, ...) = (void(*)(id, SEL, ...))[Path instanceMethodForSelector:selector]; pathFunction(shape, selector); // => Path. void(*shapeFunction)(id, SEL, ...) = (void(*)(id, SEL, ...))[Shape instanceMethodForSelector:selector]; shapeFunction(shape, selector); // => Shape. } @end