Hatena::ブログ(Diary)

Common Lisp クックブック

Common Lisp クックブックをベースにしてます。

2007-12-08

[] 4.4. すべてはオブジェクトの中にある

すべてはオブジェクトの中にある -- こんなバカバカしい思想は妄想の産物です。しかしオブジェクトシステムの多くはそう思い込もうとしていますし、理論武装もしています。CLOSオブジェクトシステムの一つとして、その考えとぶつかってみましょう。

CLOSから見た真実はこうです。アプリケーション関数とメソッド(スロットのアクセサを除く)で形作られるものであって、クラスによるものではありません。

クラスを定義したファイルに、そのクラスに適用可能なメソッドを書くこともあります。総称関数が持つすべてのメソッドを一つのファイルに書くこともあります。CLOSには言語による制限がありません。

この節のタイトルはメッセージ送信の概念とも関係があります。メッセージ送信の概念は、一つ目の引数(レシーバ)によってメソッドを決めるオブジェクトシステムから来ています。この引数が言語の特徴で、関数呼び出しの構文をその特徴に合わせると次のようになります。

Eric<-(my-describe)

これは my-describe メッセージを Eric に送ると読んでください(この例では他に引数はありません)。C++ではそのまま Eric::my_describe() と書きます。

CLOSは、複数の引数からメソッドを決定するマルチメソッドをサポートしています。あまり使うことはないかもしれませんが、他のオブジェクトシステムよりも自由というだけでなく、メッセージ送信パラダイムの制限と悪戦苦闘した犬も食わないようなコードからも解放されます。マルチメソッドの存在は、メソッドは必ずしもクラスに所属する必要がないという示唆でもあります(一つのメソッドが二つのクラスによって特定されるとしたら、どちらがメソッドの所属するクラスになるんでしょうか?)。従って、クラスを再コンパイルすることなくあなたのメソッドやその他の500のメソッドを再定義することができます。いいでしょ。

文法に関する覚え書き:マルチメソッドをサポートしない言語から拝借したと思われる、「あの」特殊な引数self と呼ぶ慣習があります。

(defmethod wibble ((self aardvark) ...) ...)

もし総称関数のメソッドが同じ引数でのみ特定されるなら、その引数を特定後のクラスの名前で呼ぶほうがましです。

(defmethod wibble ((aardvark aardvark) ...) ...)

コードは常に明確にしましょう。


練習問題

  • Lispdescribe 関数は、処理中に describe-object 総称関数を呼び出します。各処理系は各クラスにこのメソッドを実装する必要があり(ただし、standard-object 以外のクラスへの実装は任意です。また、ユーザは自由にメソッドを追加して構いません)、このメソッドがオブジェクトストリームの二つの引数を受け取るように実装しています。実装者が describe-object のすべてのメソッドを一つのファイルに書くべきか、複数のファイルに分散して書くべきか議論しなさい(例えば、aardvark で特定化されるメソッドを、クラス定義と他のメソッドと一緒に "aardvark.lisp" ファイルに書くべきかどうか)。で、どんな意見が出ましたか?
  • 二番目以降の複数の引数でメソッドを特定化しなければならない例をいくつか考えなさい。