2

Obj-C メッセージについて質問があります。

(1)それが私の主な質問です:クラスをスウィズルまたは呼び出す前に、クラスにそのスーパークラスからの実装があることを確認するにはどうすればよいですか?

ターゲット クラスでは実装されていないが、そのスーパークラスでは実装されているメソッドでメソッド スウィズリングを実行したい場合、メソッド スウィズリングの前に、このクラスがそのスーパークラスから実装されていることを確認するにはどうすればよいですか?

オブジェクトを実装していないオブジェクトにメッセージが送信されると、Obj-C ランタイムはまずその継承階層を検索して、そのスーパークラスから実装を見つけます。存在する場合、Obj-C はそれを別のディスパッチ テーブルにキャッシュして呼び出します。

このキャッシュされた実装でメソッドの入れ替えを行うことはできますか? 可能であれば、メソッドのスウィズリングまたはこのオブジェクトへのメッセージの送信の前に、キャッシュされた実装があることを確認するにはどうすればよいですか? そうでない場合、メソッドの入れ替えの前に の実装を呼び出すだけの実際の実装をこのクラスに追加するにはどうすればよいですか?super

たとえば、次のようなクラス階層があります。

@interface A : NSObject
- (void) helloWorld;
@end

@interface B : A
@end

@interface C : B
@end

@interface D : C
@end

@interface E : D
@end

そして、このような実装:

@implemenation A
- (void) helloWorld{
    NSLog(@"hello world from class A");
}
@end

@implemenation B
// did not override -helloWorld
@end

@implemenation C
- (void) helloWorld{
    [super helloWorld];
    NSLog(@"hello world from class C");
}
@end

@implemenation D
// did not override -helloWorld
@end

@implemenation E
// did not override -helloWorld
@end

-helloWorld実行時に の実装をクラスと正確に交換 (追加ではなく) したいだけですD。このトリックは、次のようなスウィズル メソッドの場合、元の実装に追加のタスクを追加します。

@implemenation D (AdditionalWorkForHelloWorld)
- (void) additionalWorkForHelloWorld{
    [self additionalWorkForHelloWorld];
    NSLog(@"hello every one!");
}
@end

したがって、 Classまたは Class-helloWorldのインスタンスにメッセージを送信すると、コンソールに次のメッセージが出力されます。DE

-> hello world from class A
-> hello world from class C
-> hello every one!

いつか、クラスが次のようにD実装し-helloWorldた後:

@implemenation D
- (void) helloWorld{
    [super helloWorld];
    NSLog(@"hello world from class D");
}
@end

Classまたは Class-helloWorldのインスタンスにメッセージを送信すると、コンソールに次のメッセージが出力されます。DE

-> hello world from class A
-> hello world from class C
-> hello world from class D
-> hello every one!

Dこのメソッド交換により、クラスが実装されているかどうかにかかわらず、追加のタスクが確実に呼び出されます-helloWorld

オブジェクトの の実装を呼び出す C 関数を作成する方法について質問superしましたが、それを行うのは簡単ではないようです。superObj-C は、メッセージをの実装に転送するために、このキャッシュされたメカニズムをどのように実現しますか?

(2) Obj-C はどのようにsuperキーワードを処理しますか? そしてどこsuperですか?

Obj-C メッセージでは、最初の 2 つの引数が隠されています:self_cmd. これらは Obj-C 実装で使用できます。しかし、どこsuperですか?

a はのポインターsuperと等しいか? Obj-C はどのようにキーワードを処理しますか?selfisasuper

すべての Obj-C メッセージはobjc_msgSend()またはに変換されobjc_msgSend_stret()ます。に送信されたすべてのメッセージは とsuperに変換されobjc_msgSendSuper()ますobjc_msgSendSuper_stret()か?

前述の例では、-helloWorldメッセージを ClassEと ClassDに送信Eして応答しない場合、Obj-C はメッセージを ClassCの実装に送信します。ClassCの実装では、その の実装を呼び出しますsuperが、 ClassBはそれを実装していないため、 Class に転送しAます。

この場合、 Class のsuperは ClassCである必要があるBため、実際には ClassBのキャッシュされた実装を呼び出しますね。BClassのキャッシュされた実装をスウィズルしてもいいですか?

4

1 に答える 1