著者: Jonathan Rees
原文: http://www.paulgraham.com/reesoo.html
日本語訳:Shiro Kawai (shiro @ acm.org)
これを翻訳したのは2004年7月頃だったのだが、 このメッセージについてRees氏に訳文公開の許可を求めたところ、 「あれは急いで書いたemailなので、きちんとした論になっていない。 できれば書き直したいと思っている。ただいつ出来るかわからないので、 私からのメイルがしばらく無かったら公開してもらって構わない」 との返事をもらった。それからもう半年経つので、公開することにした。 ただ、読む場合は著者本人が上記のように思っていることを留意して頂きたい。
また、原文が書かれたのは2002年であることにも注意。 いくつかの事実は古くなっているかもしれない。
2005/01/23 翻訳公開
「なぜArcはとりたててオブジェクト指向ではないのか」 に対して、Jonathan Reesが非常に興味深い意見を寄せてくれた。 彼の許可を得てそれを公開する。
以下に示すのは、[オブジェクト指向にまつわる]用語に関連づけられる機能や特性の メニューだ。オブジェクト指向というのは、このリストのいろいろなサブセットとして 定義されているようだ。
カプセル化 - 型の実装を構文的に隠蔽できること。 例えばCやPascalでは何かが構造体であるか配列であるか常に意識することに なるが、CLUやJavaではその違いを隠すことができる。
保護 - 型の使用者がその実装をのぞくことができないこと。 これによって、ふるまいさえ変えなければ、実装を変更しても型の使用者に 影響を与えないことが保障でき、またパスワードのような情報が漏れ出さないように することもできる。
アドホックポリモルフィズム - 関数やパラメータつきデータ構造が たくさんの異なる型の値をとることができる。
パラメトリックポリモルフィズム - 関数やデータ構造が任意の値 (例:任意のオブジェクトのリスト)に対してパラメタライズできること。 MLとLispはこれを持つ。Javaは非Objectな型のために、これを完全に持つとは言えない。
全てはオブジェクトなり - 全ての値はオブジェクト。Smalltalkでは真だが、 Javaでは (int等のため) 真ではない。
メッセージを送ることだけができる (All you can do is send a message, AYCDISAM) = Actorモデル - オブジェクトを直接いじることはできず、それと通信する、もしくはそれを起動する ことのみができる。Javaにおけるfieldの存在はこれに反する。
仕様継承 = サブタイピング - ふたつの異なる型で、一方の型の値が もう一方の型の値として使われても型の正当性を破らないことを言語が保障できるような もの。(例: Javaのインタフェース継承)。
実装継承, 再利用 - ひとまとまりのコードを書いたら、 それと似たコード (そのスーパーセット) が制御された方法で生成できる。 つまりコードをコピーして編集する必要がない。制限された、特殊な抽象化である。 (例: Javaのクラス継承)。
「関数の積和(sum-of-product-of-function)」パターン - オブジェクトは (実質的に)有限の簡単な名前の集合から選ばれるキー引数を第一引数に取り、 それによってメソッドを呼び出す関数として動作する。
つまり、「オブジェクト指向」というのはちゃんと定義された概念ではない。 ある人々 (AbelsonとSussman?) はLispはオブジェクト指向だと言うが、 それは {3,4,5,7} に基づく (但し、全ての型はプログラマの頭の中に存在するとする)。 Javaは {1,2,3,7,8,9} があるからオブジェクト指向だ。 Eは {1,2,3,4,5,7,9} と6のほとんどをもつから、もっとオブジェクト指向だと 言えるかもしれない。だが 8 (サブクラス) はEのゴールには反するもので、 オブジェクト指向にとって必要なものとはみなされない。
伝統的なSimula 67風のクラスとインスタンスのパターンは、 {1,3,7,9}の特徴を持つ。たぶん、多くの人が考えているオブジェクト指向の 定義はそれではないか。
オブジェクト指向というものが動く標的であるため、 オブジェクト指向の熱心な支持者はこのメニューのうちの適当なサブセットを 気まぐれに選んで、それを以って他の言語はオブジェクト指向ではないと 説得しようとする。
おそらく、混乱のもとのひとつは (そして、これは君(Paul)が 君の小さなメモで別の言い方で述べていることだが)、 C/C++プログラマにとってオブジェクト指向は第一級の関数に類するものが存在しない 世界からの開放であったのに対し、Lispプログラマにとってはオブジェクト指向は 関数やオブジェクトを9のスタイルで使うことを制限する牢獄になる、ということでは ないだろうか。そうだとしたら、オブジェクト指向を弁護する唯一の方法は、 他のゲームや戒律と同じようなものになる---すなわち、 何か(例えば近所の家に卵を投げつける自由)をあきらめることで、 欲しい何か(たとえば近所の人があなたを牢屋にぶちこんだりしない保障)を得ることができる、 というものだ。
これはまた、Lispが孤独なハッカーに好まれるのに対し、 規律を守ることを要求する言語が多数派に好まれるという、 君が言及しているもうひとつの点にも関連している。 大衆の中では、他人が自分に干渉したり自分を利用したりしないように、 各人の自由を制限すべきだと誰もが思うだろう。そうするためには、 自分が酋長になるか (だが危険だし、難しい)、それともみんなが従うルールに 自分も従うしかない。ルールに従うことになれば、自分がやりたいことは だいたい自由に出来るけれど、他人が自分の足をふんづけられるほど自由ではない、 というルールに落ち着くだろう。
このような大衆的プログラミングの世界では、言語とは憲章か法律のような もので、インタプリタ/コンパイラ/QA部門は法の検査/強制、あるいは警察力の 一部としての役割を果たす。同僚は知りたがるだろう: もし自分があなたの コードと一緒に働くことになったとして、それは自分にとって有利なのか 不利なのか? 正当性というのは一般的に決定不可能なので (それに強制できるようなものではないので)、マネージャはプロジェクトが 始まった時に何であれ見つけたルール(静的型システム、言語による制限、 "lint"プログラム等々)を使って行くことになる。
最近、私はe-langのメーリングリストにて、反オブジェクト指向の議論に 加勢した。私の反オブジェクト指向のメッセージの主要な部分 (実際は ポイント5,6についてだけ攻撃しているのだが)は http://www.eros-os.org/pipermail/e-lang/2001-October/005852.htmlだ。 これに対する返信も興味深いが、ウェブページではメッセージのスレッドが ちゃんと表示されていないようだ。
(上で使われている用語の簡単な定義:値 = 関数(抽象)に渡せる何か。マクロパラメータとかパラメタライズ された型やモジュールといった、コンパイル時に作用する変なものは除く。
オブジェクト = 関数のようなふるまいを持つ値。すなわち、 それに対してメソッドを起動したり、それ自身を呼び出したり、 メッセージをそれに対して送ったりできること。 「オブジェクト」を、上記の9の点に従ってもっと厳密に定義する人もいるが、 もっと広い範囲のものを指すのに使う人もいる(例: CLTL)。 このせいで、「全てはオブジェクト」は、明確な定義のない空疎な言明となってしまっている。
いくつかの言語では「呼び出し」はカリー化されるし、 キーからメソッドへの写像がコンパイル時に行われるものもある。 そのせいで、C++系の言語におけるオブジェクト指向の議論が曖昧なものに なるかもしれない。
関数 = 特定のパラメータと合わせて何かの結果を生成することができるもの。 言語によって、それはオブジェクトと同じである場合もあるし、違う場合もある。
型 = 関数が意味のある方法でパラメタライズできる、値の取り得る空間を 記述するもの。ここでは、言語に明示されている型も、プログラマの頭の中や ドキュメントにだけ示される型も含む。
訳出しなかったが、Jonathan Reesが示しているふたつのリンク (e-langメイリングリスト のポストとそれに対するリプライ、およびすぐ上の「完全なやりとり」) は ここでの議論を深く考える上で重要だ。もしこの文章を読んで疑問を覚えたら、 ぜひ参照して欲しい。e-langメイリングリストのJonathanの リプライにおける、declarative/imperative programmingの二重性など 興味深い。