Objective-C を使用したプログラミングの Apple の「メッセージング」の章を読みましたが、self と super についていくつか質問があります。私の知る限り、コンパイラがメッセージを見つけると、レシーバー、セレクター、およびセレクターの可変引数を使用して、それを objc_msgSend に変換します。たとえば[self test]
、次のようになります。
objc_msgSend(self, @selector(test));
レシーバーのディスパッチ テーブルにメソッドの実装がない場合、関数はスーパークラスで実装を見つけようとします。super は、コンパイラが現在のオブジェクトのスーパークラスでメソッド実装の検索を開始するための単なるフラグであり、ドキュメントでは、コンパイラが「スーパー」を見つけると、次のように変換すると述べています。
struct objc_super mySuperClass = {
self,
[self superclass]
};
objc_msgSendSuper(&mySuperClass, @selector(forwardedMethod));
私は 3 つのクラスを持つプロジェクトを作成しました。それぞれが別のクラスを継承しています。
@interface FirstClass : NSObject
- (void)forwardMethod;
@end
@interface SecondClass : FirstClass
@end
@interface ThirdClass : SecondClass
@end
ルート ビュー コントローラーで 3 番目のクラスのインスタンスを作成し、'forwardMethod' というメソッドを呼び出します。実装:
//First Class
- (void)forwardMethod {
NSLog(@"Base class reached");
}
//SecondClass imp
- (void)forwardMethod {
NSLog(@"second class");
[super forwardMethod];
}
//ThirdClass imp
- (void)forwardMethod {
NSLog(@"third class");
[super forwardMethod];
}
すべて正常に動作します。しかし、その後、コンパイラを解釈することにしました:
//First Class
- (void)forwardMethod {
NSLog(@"Base class reached");
}
//SecondClass imp
- (void)forwardMethod {
NSLog(@"second class");
struct objc_super mySuperClass = {
self,
[self superclass]
};
objc_msgSendSuper(&mySuperClass, @selector(forwardMethod));
}
//ThirdClass imp
- (void)forwardMethod {
NSLog(@"third class");
struct objc_super mySuperClass = {
self,
[self superclass]
};
objc_msgSendSuper(&mySuperClass, @selector(forwardMethod));
}
これにより、2 番目のクラス「forwardMethod」が再帰的に呼び出されます。self と [self superclass] を使用して 2 番目のクラスで 'forwardMethod' に構造体を作成しますが、self は 3 番目のクラスであり
、私のスーパークラスは常に '2 番目のクラス' になります。たぶん私は何か間違ったことをしているのですが、基本クラスの「フォワードメソッド」にアクセスするにはどうすればよいですか?