なぜ Objective-C はメッセージ式なのか

Objective-C が奇妙に見える大きな要因のひとつは、明らかにメッセージ式の存在だと思います。なぜ Objective-C はメッセージ式という奇妙な式を用いてメソッドを呼び出すようになったのでしょうか? Objective-C の作者にどういった意図があったのかは知りませんが、私なりに Objective-C がメッセージ式でなければいけない理由を見つけていますので、そのお話をしようと思います。

まず、他の多くの言語で採用されている、 . によるメンバアクセスによるメソッド呼び出しを考えてみましょう。

anObject.method( );

みなさんはこれをどう解釈するでしょうか? インスタンス anObject の method メソッドを実行する。そう解釈するのが普通だと思われます。なぜなら、 . は、多くの場合メンバへのアクセスを意味するもので、 anObject のメンバである method メソッドを呼びだすと考えることができるからです。

call method

それでは、こちらはどうでしょうか?

[anObject method];

みなさんはこれをどう解釈するでしょうか? anObject の method メソッドを実行するでしょうか?そう思った方は、まだ Objective-C に不慣れな証拠です。これは、 anObject に method メッセージを送信すると解釈すべきです。

send message

Objective-C では、オブジェクトがメッセージを受け取ること、すなわちメソッドの実行というわけではありません。現実としては、対応するメッセージの実装が呼び出されていますが、それをメソッド呼び出しと呼ぶことには、再考の余地があります。

例えば、Objective-C では、デリゲートがあります。デリゲートは、メッセージを受け取ったオブジェクトが、デリゲートオブジェクトにメッセージを転送し、そのデリゲートのメソッドに委譲して処理させるための仕組みです。この場合、誰がメソッドを実行していますか?デリゲートオブジェクトです。すなわち、必ずしもメッセージを受け取ったオブジェクトが、実際に処理するメソッドを実行しているわけではないのです。メッセージを受け取ったオブジェクトは、メッセージを転送するという処理のメソッドを実行しているのです。

例えば、 Objective-C では、オブジェクトにどんなメッセージを投げることも許容しています。 . によるメンバへのアクセスならば、メンバが無い時点でエラーを出すべきであり、コンパイル時にエラーを出します。しかし、 Objective-C の場合、たとえ実装のないメッセージでも、コンパイル時は警告のみで、コンパイルすることは可能です。これは、オブジェクトはどんなメッセージも受け取るということです。

受け取ったメッセージに対応するメソッドの実装がなかった場合、そのメッセージはどうなるでしょうか?何もしなければ例外が発生するようにできていますが、 Objective-C ではそのようなメッセージを処理する仕組みが用意されています。 methodSignatureForSelector: と forwardInvocation: を適切にオーバーライドすることによって、対応する実装のないメッセージに対して、処理をすることができます。処理の内容は、代わりに適当なメソッドを実行させるようにしたり、別なオブジェクトにメッセージを転送したり、例外を発生させたりと、さまざまな処理を記述することができます。

Objective-C では、メッセージとメソッドを分けて考えるべきだと思います。 . によるメソッド呼び出しの記述は、まさにそのオブジェクトのメソッド実行を意味しますが、オブジェクトへのメッセージ送信は、必ずしもメソッド実行と結びつかないわけです。メッセージ送信のイメージは、メソッド実行ではなく、オブジェクト同士の会話を想像すべきです。メッセージ送信先の相手が、どのようにメッセージを解釈しようと、適切に返事をしてくれさえすれば、何も気にすることはないのです。

メッセージ式に慣れてくれば、この [ ] を見ると、オブジェクトにメッセージを投げているように見えてくるはずです。そして、 . とは違う意味があることに気がつくことでしょう。

コメント

  1. [...] こたつつきみかん » なぜ Objective-C はメッセージ式なのか [...]

コメント投稿