Objective Cには、他のオブジェクトにメッセージを送信するという概念があります。これは、C#やJavaなどの言語でのメソッド呼び出しによく似ています。
しかし、どのような正確に微妙な違いがありますか?私のコードについて考えるとき、どのようにメッセージングを考える必要がありますか?
注:ここで少し背景を説明しますが、私はObjective Cに関するいくつかの概念を理解しようとしているC#/ Java開発者です。
Objective Cには、他のオブジェクトにメッセージを送信するという概念があります。これは、C#やJavaなどの言語でのメソッド呼び出しによく似ています。
しかし、どのような正確に微妙な違いがありますか?私のコードについて考えるとき、どのようにメッセージングを考える必要がありますか?
注:ここで少し背景を説明しますが、私はObjective Cに関するいくつかの概念を理解しようとしているC#/ Java開発者です。
回答:
メッセージは、セレクターの名前、およびそのセレクターのパラメーターです。
セレクターはシンボルです。
メソッドは、セレクターによって識別されるクラス内のコードです。
言い換えれば、[foo bar: baz]
「@selector(bar:)
パラメーター付きで呼び出されたメッセージbaz
をオブジェクトにfoo
送信します。そのメッセージを多くの異なるオブジェクトに送信できます。
対照的に、のメソッド bar:
は次のFoo
ようになります
-(int)bar:(int)n {
return n + 1;
}
しかし、のFooTwo
ように見えるかもしれません
-(int)bar:(int)n {
return n + 2;
}
(構文が正しいことを願っています。Objective-Cに最後に触れてからしばらく経ちました。)
メッセージを送信すると、Objective-Cカーネルはメッセージをディスパッチし、メッセージをfoo
理解するかどうかを決定します。そのセレクターによって識別されたメソッドを見つけることができるかどうかに基づいて、これを決定します。
同じ名前の2つのメソッドと1つのメッセージ。
オブジェクトが特定のメッセージ(またはメッセージのセット)を処理のために別のオブジェクトに単に転送することも可能です。この場合、このプロキシオブジェクトにメッセージを送信します。このプロキシオブジェクトには、そのメッセージに一致するメソッドがなく、プロキシはラップされたオブジェクトにメッセージを転送します。
純粋に理論的な観点からは、この2つの間にまったく違いはありません。2つが完全に同等であり、どちらかが他方に関して完全に実装できることを示す正式な証明がいくつかありました。
わずかに理論的な観点からは、考えられる違いが1つあります。典型的な実装では、仮想関数テーブルは静的に割り当てられ、各vtableの内容はコンパイル時に固定されます。対照的に、メッセージルックアップは通常、何らかのマップのようなオブジェクトを使用して実行されます。これは通常動的であり、実行時に変更できます。これにより、既存のクラスのメッセージに新しい応答を比較的簡単に追加できます。残念ながら、ほとんどの場合、これはほとんど理論的なままです。最初に、あなたは基本的に自己修正コードを扱っています。ほとんどの人は長い間かなり悪い考えだと判断しました時間前。第二に、それを非常に意味のあるものにするためには、サポートする新しいメッセージに応答するために、既存のクラスに新しいコードをコンパイルできる必要があります。それなしでは、既存のメソッドに新しい名前を動的に追加することができます。
前の段落の終わりに暗示されているように、真に実用的な観点からは、両者の間にほとんど違いはありません。これらは、レイトバインディングをサポートする2つの(非常にわずかな)異なる方法です。メッセージベースのルックアップは一般に少し遅いですが、違いが本当に重要になることはかなり珍しいでしょう。最も実用的な目的では、同じことを達成するための2つの異なる方法にすぎません。
通常、メソッド呼び出しはコンパイル時に解決されます(Javaでリフレクションを使用しない限り)が、Objective Cのメッセージは実行時にディスパッチされます。
struct
、最初のパラメーターとして取得するオーバーロード関数に構文シュガーを使用しています。後期バインドは多型、したがってOOPの重要な部分です。
メッセージは、カーネルまたは言語自体によって処理されます(たとえば、ObjCの場合、それを行う非常に小さなアセンブリコードがあります)。
たとえば、Linuxカーネルでは、メッセージはシステムコール/関数で処理されます。Unixシステムプログラミングについて検索すると、メッセージを見つけることができます。
メソッド呼び出しとメッセージの中心的な違いは次のとおりです。
メソッド呼び出しはコード内でのみ発生します。ASMでは、渡された引数のPUSHによって変換されます。
カーネルメッセージはほとんどがカーネルに送信され、追跡されて特定のプロセスに送り返されるものです。私はそれらをパイプと間違えるかもしれませんが、何でも:複数のプログラムを同時に実行し、同時に通信できるようにするメカニズムが既にあることを知っています。もちろん、これがWindowsや他のOSでも同じように機能することを期待しないでください。