メッセージとメソッドの違いは?


13

Objective Cには、他のオブジェクトにメッセージを送信するという概念があります。これは、C#やJavaなどの言語でのメソッド呼び出しによく似ています。

しかし、どのような正確に微妙な違いがありますか?私のコードについて考えるとき、どのようにメッセージングを考える必要がありますか?

注:ここで少し背景を説明しますが、私はObjective Cに関するいくつかの概念を理解しようとしているC#/ Java開発者です。


2
それらはすべて異なる言語なので、違いは微妙ではありません。それらは異なる言語です。「私のコードについて考えるとき」?どのコード?JavaまたはC#について考えるとき、メッセージについては考えません。メソッドについて考えます。無関係な概念を持つ無関係な言語が「微妙な」違いをどのように持つかを明確にできますか?
S.Lott

1
stackoverflow.comで質問してください
Amir Rezaei

1
この質問は本当にStackOverflowにありますか?それはプログラミングの概念に関する問題であり、私が持っているコードの問題ではありません。たぶん私が間違っている、私は知らない-境界が...ぼやけている
Vidar

1
@Vidar、質問は主観的ではありません。教科書の定義を探しています。プログラマーは、意見、経験、主観的な質問に重点を置いています。
スティーブンフルラニ

1
OK-モデレーターにこの質問をStackOverflowに移動させる方法はありますか?
ヴィダー

回答:


10

メッセージは、セレクターの名前、およびそのセレクターのパラメーターです。

セレクターはシンボルです。

メソッドは、セレクターによって識別されるクラス内のコードです。

言い換えれば、[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つのメッセージ。

オブジェクトが特定のメッセージ(またはメッセージのセット)を処理のために別のオブジェクトに単に転送することも可能です。この場合、このプロキシオブジェクトにメッセージを送信します。このプロキシオブジェクトには、そのメッセージに一致するメソッドがなく、プロキシはラップされたオブジェクトにメッセージを転送します。


so ...メッセージはdispinterface(a.invoke selector、args)を呼び出したときであり、メソッドはinterface(a.methodName)を呼び出したときですか?Java、JavaScript、すべての動的言語にはメッセージがありますか?すべてが直接的なジャンプとvtableジャンプへのオフセットではなく、デュアルインターフェイスを介して行われるためです)?
ドミトリー

3

純粋に理論的な観点からは、この2つの間にまったく違いはありません。2つが完全に同等であり、どちらかが他方に関して完全に実装できることを示す正式な証明がいくつかありました。

わずかに理論的な観点からは、考えられる違いが1つあります。典型的な実装では、仮想関数テーブルは静的に割り当てられ、各vtableの内容はコンパイル時に固定されます。対照的に、メッセージルックアップは通常、何らかのマップのようなオブジェクトを使用して実行されます。これは通常動的であり、実行時に変更できます。これにより、既存のクラスのメッセージに新しい応答を比較的簡単に追加できます。残念ながら、ほとんどの場合、これはほとんど理論的なままです。最初に、あなたは基本的に自己修正コードを扱っています。ほとんどの人は長い間かなり悪い考えだと判断しました時間前。第二に、それを非常に意味のあるものにするためには、サポートする新しいメッセージに応答するために、既存のクラスに新しいコードをコンパイルできる必要があります。それなしでは、既存のメソッドに新しい名前を動的に追加することができます。

前の段落の終わりに暗示されているように、真に実用的な観点からは、両者の間にほとんど違いはありません。これらは、レイトバインディングをサポートする2つの(非常にわずかな)異なる方法です。メッセージベースのルックアップは一般に少し遅いですが、違いが本当に重要になることはかなり珍しいでしょう。最も実用的な目的では、同じことを達成するための2つの異なる方法にすぎません。


2
証拠を示す参考文献はありますか?見てみたいです。Javaのメソッド呼び出しとSmalltalkのメッセージ送信には、バインディングが遅いだけでなく、送信者と受信者の分離のために大きな違いがあります。メッセージの受信者がメッセージを処理するのか、メッセージを転送するのかわかりませんたとえば、
フランクシェラー

1

Objective-Cでは、メッセージは遅延バインドされます。つまり、実行時に解決されます。C#は、オブジェクトが遅延バインディングであると宣言するDynamicキーワードを通じて同様の構成をサポートします。


0

通常、メソッド呼び出しはコンパイル時に解決されます(Javaでリフレクションを使用しない限り)が、Objective Cのメッセージは実行時にディスパッチされます。


2
メソッド呼び出しがコンパイル時に解決される場合、OOPを使用せずstruct、最初のパラメーターとして取得するオーバーロード関数に構文シュガーを使用しています。後期バインドは多型、したがってOOPの重要な部分です。

2
はい。ただし、コンパイル時によく知られている(Javaの)ものに対してメソッド呼び出しをコーディングすることしかできません。MyObjectまたはMyInterfaceにメソッドfoo()が定義されていない場合、MyObject.foo()を呼び出すとエラーが発生します。ObjCは、メッセージ 'foo'をオブジェクトMyObjectに送信することを許可します。MyObjectに 'foo'がない場合、実行時に爆撃されます。
ハイコラップ

Objective Cはコンパイルされた言語だと思いましたか?
ヴィダー

1
これは、早期/後期バインディングに対応していません(動的タイピングと構造タイピング-例では、メソッド呼び出しはコンパイル時にチェックされますが、必ずしもディスパッチされるわけではありません)。@Vidar:そうですが、動的機能に魔法を加えます。Pythonをコンパイルすることもできます。

@Vidar:コンパイルされたもの対解釈されたものの問題ではなく、静的なものと動的なものの問題です。Javaのような静的OOP言語では、コンパイラーはコンパイル段階でクラスがメソッドを定義することを確認します。Objective-Cのような動的に型付けされた言語では、メッセージは実行時に渡されます。
ミパディ

-1

メッセージは、カーネルまたは言語自体によって処理されます(たとえば、ObjCの場合、それを行う非常に小さなアセンブリコードがあります)。

たとえば、Linuxカーネルでは、メッセージはシステムコール/関数で処理されます。Unixシステムプログラミングについて検索すると、メッセージを見つけることができます。

メソッド呼び出しとメッセージの中心的な違いは次のとおりです。

  • メソッド呼び出しはコード内でのみ発生します。ASMでは、渡された引数のPUSHによって変換されます。

  • カーネルメッセージはほとんどがカーネルに送信され、追跡されて特定のプロセスに送り返されるものです。私はそれらをパイプと間違えるかもしれませんが、何でも:複数のプログラムを同時に実行し、同時に通信できるようにするメカニズムが既にあることを知っています。もちろん、これがWindowsや他のOSでも同じように機能することを期待しないでください。


これはプログラミング言語に適用されるため、「メッセージの受け渡し」ではありません。
ミパディ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.