PMD
Prototypes with Multiple Dispatch。プロトタイプベース・オブジェクト指向で、なおかつCLOSの総称関数のような多重ディスパッチを行う仕組み(モデル)。
メソッド定義は複数のオブジェクト(インスタンス兼クラス)に共有される。
CLOSのメソッドはクラスに属さずに総称関数に属するが、PMDの言語ではあくまでオブジェクト自体がメソッドを持つ。
各オブジェクトは単にメソッドを他のオブジェクトと共有するだけでなく、メソッドの何番目の引数を演じることができるか(これを「役割」と呼ぶ)を知っている。この情報がないと演じることのできない役割まで担おうとしてしまうかもしれない。
メソッド定義のしかたそのものはPMDの言語でもCLOSでもあまりかわりない。違いはクラス変更(デリゲート変更)の自由さにある。総称関数のやり方だと、コンパイル時に解決してしまうことが多いらしく、プロトタイプベース的な実行時の自由なクラス変更までは難しい。
実はCLOSにも、既存のインスタンスのクラスを変更するためのchange-classという総称関数が備わっているんだけど、無理矢理にでもプロトタイプベースのような感じで使えないのかな・・?
と思ったけど、CLOSではインスタンスが直接複数のクラスに属するわけではないので、クラスを丸ごと取り替えるしかできないみたい。
PMDだと多重ディスパッチとプロトタイプベースのそれぞれが目標としていたことを同時に実現できる。実は、これらは両方とも「複雑なif文が不要になる」ということで「宣言的」な言語のための仕組みである。
・多重ディスパッチの効能:
もしメソッドの引数として受け取った値のクラスを調べて処理をわけているとしたら、動的束縛と同じ処理を手でやっていることになる。レシーバだけでなく引数のクラスも考慮してメソッドを選ぶ仕組みがあれば、if文でやっていた分岐をメッセージ受け取りの枠組みの中で箇条書きにして総合的に整理できる。
・プロトタイプベースの効能(のひとつ):
プロトタイプベースではインスタンスは複数のクラスに同時に属することができ、実行時にどのクラスに属するかを変更できる。
もしオブジェクトの内部状態をif文で調べて処理をわけていたら、内部状態を「どのデリゲートを選ぶか」によって表現することで、メソッド内部に隠されたif文のロジックを表に出して宣言的に表現できる。つまり、内部状態の変更をデリゲート変更とし、メソッドディスパッチをデリゲート選択によって変わるようにすれば、これもメッセージ受け取りの枠組みの中で箇条書きにして整理できる。
よくよく考えてみれば、これは一般的なオブジェクト指向言語における制限を撤回しただけのことで、オブジェクト指向が本来持っているパワーを素直に広く活用できるようにしたということになるのだろう。
ランタイムの実装は非常に複雑になるが、魅力的なモデルである。
--やまねこ
PMDの効能はもうひとつある。
CLOSの総称関数の名前はパッケージで分割しないと名前がぶつかりやすくて困るという問題があった。
たとえばresetという名前の3つの必須パラメタをもつ総称関数を定義したとする。このあと同じresetという名前で必須パラメタが2つの総称関数をもうひとつ定義することはできない。この場合、resetという名前があまりにも一般的すぎるのが悪いとされるが、実際にどの程度長い名前をつければいいかは他の総称関数の数しだいである。
この問題に関しては、確かに、いくらメソッドの名前(セレクタ)が同じなのが多態性の原理だとはいってもそれは同じ意味を持つメソッドどうしで言えることであって、違う意味を持つのに名前が同じメソッドを複数定義するのは不都合がある。
それでもクラス階層の中で互いに干渉しあわない位置にある複数のクラスでたまたま同じ名前のメソッドがあっても実行には差し支えないはずである。実際、この状況でコンパイラが警告してもそれを無視して実行できるということをObjective-Cで確かめた。(Objective-Cは常に動的にメソッドを決定するのでこうなる)
メソッドを総称関数に属させる場合はひとつの総称関数がパラメータパターンを確立してしまって、他のパターンを許さない。
しかし、オブジェクトの側で持たせる場合は、ひとつのオブジェクトの中で名前がぶつかりさえしなければかまわないという違いがある。
とりあえずPMDの言語であるSlateはObjective-Cと同じようになると思われる(たぶん、、いまだ実験してないけど^^;)
この問題はPMDが解決するわけではない。結局は名前空間をわけることが必要なのだろう。しかしメッセージに対する具体的反応動作だけでなく、メッセージの意味もオブジェクトにあわせて変わるほうがオブジェクト指向至上主義といえるかもしれない。
--やまねこ
このページを編集 (3889 bytes)
|
以下の 2 ページから参照されています。 |
- 総称関数 最終更新: 2005-05-15, 00:03:55 <p3097-i>
- Slate 最終更新: 2006-04-26, 10:34:16 <khp0591>
This page has been visited 3924 times.