メッセージ送信

2007/03/30 (Fri) 22:07:46 JST

メッセージ送信

前回はインスペクタを使ってオブジェクトの中身を覗いてみました。今度はオブジェクトを操作してみましょう…といきたいところですがその前に、誰がどうやってオブジェクトを操作するのでしょうか。

他の言語では「関数」がデータを操作します。関数は扱えるデータ型が決まっていて、データに応じてプログラマが関数を選択します。オブジェクト指向プログラミングにも関数に相当する「メソッド」というものがあり、「メソッド」を使ってオブジェクトを操作することになります。ただし、メソッドは関数と違ってプログラマが選択・指定するものではありません。実はオブジェクト自身が自分に対して使うべきメソッドを決定します。つまり、オブジェクトは自分で自分を操作するのです。

プログラマはオブジェクトに対して自分自身を操作するよう促す「メッセージ」を送ります。これを平たく言えば、オブジェクトに指示を出します。指示をどう解釈し、どう動く (メソッドを実行する) かはオブジェクトが自主的に判断することです。(通常はメッセージと同名のメソッドが実行されます)

この、間接的にオブジェクトを操作する仕組みを「メッセージ送信」と言います。関数呼び出しの間にワンクッション入れただけのささいな違いですが、これが結構あとから効いてきます。

メッセージ

国語辞典にはこうあります。

英英辞典にはこうあります。

私は「メッセージを送る」という日本語が、オブジェクトに対して消極的なようで少し違和感がありますが、英語圏の人には自然な表現のようです。

オブジェクトを操作する

それではメッセージを送ってオブジェクトを操作してみましょう。次の式をワークスぺースに書いて、再びaltキーを押しながら左クリックをします。メニューから「式を表示する」を選択してください。

#(1 2 3) at: 1

"1" と表示されます。#(1 2 3) が配列、最後の "1" が引数となります。この引数とその間にある at: を含めた式が「メッセージ」です。コロンの次には必ず引数が続きます。メッセージ at: を配列に対して送ると、配列のn番目のオブジェクトが返ってきます。(一般的な言語と異なり、Smalltalkでは配列のインデックスが1から始まります)

もう一つメッセージを送ってみましょう。上と同じように「式を表示する」を選択してください。

#(1 2 3) at: 1 put: 5

一見2つのメッセージを送っているようですが、実はこれで2つの引数をとる1つのメッセージです。引数が 1, 5 のメッセージ at:put: をオブジェクトに送っています。

さて、今度は "5" と表示されます。at:put: は配列の内容を入れ替えるメッセージですが、戻り値が入れ替える値になるので "5" と表示されます。これでは肝心の配列の内容が変更されたかどうかわかりませんね。

ここでインスペクタを使ってみましょう。配列 #(1 2 3) を選択して「式をインスペクト」します。

左上のウィンドウ、インスタンス変数のリストに配列の各要素が一緒に並んでいます。「なんでインスタンス変数に配列の要素があるのか」と思われるかと思いますが、そこには大人の深い事情があるのです。今はそっとしておきましょう。

さて今回使うのは下のウィンドウです。下にあるウィンドウはちょっとしたワークスぺースになっていまして、ここでもコードを書いて実行することができます。一つ違うのは、インスペクタで覗いているオブジェクトにもメッセージを送れることです。

インスペクタで今覗いているオブジェクトは self で表します。が、メッセージを送る前にインスタンス変数の "1" を選択しておき、右上のウィンドウに1番目の内容を表示させておきましょう。

そうしたら下のウィンドウに次の式を書きます。

self at: 1 put: 5

いつものクリックで実行メニューを開き、今度は「式を評価する」を選択します。右上のウィンドウに注目していてください。

評価後はこうなります。

どうですか?変わりましたか?今送ったメッセージで配列の内容が変わりました。オブジェクト指向プログラミングではこのようにしてオブジェクトを操作します。

「なんだ関数と変わらないじゃないか」と思った疑り深いアナタ、そうですそうです見た目も結果もたいして関数と変わりません。使っているうちに違いに気づけばいいことです。今の段階ではオブジェクトの操作方法がわかれば十分です。

プログラミング言語とメッセージ送信

オブジェクト指向を標榜するプログラミング言語なら必ずメッセージ送信を行う、というわけではありません。メジャーどころですとSmalltalk, Objective-C, Rubyではメッセージ送信を行いますが、C++, Java, Perl, Python, PHPではメッセージ送信を行いません。ならどうやってメソッドを起動しているのかというと単にメソッド名を指定するだけで、(ほぼ) 関数と同じです。それでもメッセージ送信とほとんど同じことができます。

「メッセージ送信がないならオブジェクト指向の意味がない?」ということはありません。メッセージ送信にもデメリットはありますし、メッセージ送信以外にもオブジェクト指向のメリットはあります。言語には言語の哲学があるのです。

まとめ

ポリモルフィズムに続きます。


Inverse Pages: ポリモルフィズム オブジェクトとは何か Squeakによるオブジェクト指向プログラミング入門 VisualWorks:パフォーマンスチューニング VisualWorks:バイトコードセット VisualWorks:インライン展開