Java のクラスはオブジェクトじゃない?!


関連:id:sumim:20040525:p1


keisuken さんの 航海日誌 発、babie さんの 遅レス 経由で、オライリーオープンソースコンベンション(OSCON 2005)のセッション「10 Things Every Java Programmer Should Know About Ruby」(スライドbrazil さんの和訳)で語られた「Item #9 Everything is an Object」から生じる語弊について。


そうですね。これではまるで Java のクラスがオブジェクトではないかのように読めますし、そうだとすれば(オブジェクトに定義にもよりますが、おそらく)間違いでしょう。ただ、文脈をたぐると、ここでの Jim Weirich さんの主張は「(Ruby において)“Array”は、Array というクラス(を実現した)オブジェクトを束縛した定数(に過ぎない)」(Array is a constant name that is bound to the Array class object.)であり、このことは、「新しいオブジェクトを作るのに(“new クラス名”という)特別な文法を必要としない」(Creating new objects does not require special syntax.)といった効果を生じさせる、ということのようにとることができます。つまり「Java のクラスがオブジェクトではない」ということを言いたいのではなく「Java のクラスに new メッセージを送ってもインスタンスは作れない」ということに言及していると、そんなふうに読めますから、まあそれならOKかな…という感じもしなくもありません。


追記
id:babie さんからのご指摘によると、そもそもの発端は、同じ Jim Weirich さんですが違うセッション「Dependency Injection: Vitally Important or Totally Irrelevant?」の「Java Classes vs Ruby Classes」で「(Java classes are) Not Object」とずばり述べているところからだそうです。


ところで、「new クラス名」という書き方は SIMULA 67(のちに SIMULA に改名)にさかのぼることができるのですが、これをそのまま使った「new クラス名」か、はたまた“クラスへの new メッセージ送信”かのどちらが“オブジェクト指向”に相応しいかは、その“オブジェクト指向”において想定されるパラダイムが「クラス指向」か「メッセージ指向」のどちらに主軸を置くのか、という問題に大きく関わってくるものだと個人的には考えています。すべてがオブジェクトか否か、静的型チェック機構があるか否か、についても根っこは同じでしょう。



「クラス指向」つまり、抽象データ型のスーパーセット、あるいは「カプセル化 + 継承・多態性」の三要素を必須とするオブジェクト指向パラダイムにおいては、ユーザーが定義したデータ型(抽象データ型)を継承を使って手軽に定義でき、そうして作られたユーザー定義型を基本型と同じように扱えることがもっとも大切なことのひとつとされます。そしてこの考え方を実践した最初の言語である C++ では、ユーザー定義型を実現する仕組みに(SIMULA の)「クラス」を用いました。扱えるデータ型すべてがユーザー定義型であっても構いませんが、そうであるメリットはあまり多くありません。余談ですが、データ型とその安全な運用に重きを置いていますから、静的型チェック機構はある意味、必須です。


この考え方において「new クラス名」、つまり“あなたが(あるいは誰かが)定義したデータ型に属する新しいデータ(を作る)”という記述は、比較的しっくりとします。



「メッセージ指向」つまり、(パーソナルコンピューティングに関わる)すべてを(オブジェクトへの)メッセージ送信で表現しようとする考え方、あるいはケイの「間(ma)指向」においては、あらゆるものを、いかにして“メッセージング”で実現するかということに軸足が置かれています。つまり、小さなコンピュータ同士が“メッセージ”を介して、高速のネットワークで接続されている状況を想定し、そこに解決したい問題を細分化し当てはめてゆく、そんな作業とそれを支援するシステムが必要とされます。そしてこの考え方を実践した最初のシステムである Smalltalk では、メッセージを受信する小さなコンピュータに(SIMULA の)「オブジェクト」を用いました。すべてのものはメッセージを受信する能力を期待されますから、すべてがオブジェクトであることは比較的重要です。クラスは必須ではありませんが、効率を考えるとあったほうが便利でしょう。ただしその場合、クラスもオブジェクト、つまり、メッセージを受信できることが当然のように期待されます。


この考え方において“クラスへの new メッセージ送信”により新しいインスタンスが生成されることは、とても自然なことです。



Java はクラス指向に立脚しています。個人的には Java は、Eiffel が途中で投げ出してしまったクラス指向を踏襲しつつ、Smalltalk システムがメッセージ指向により構築した世界観をクラス指向で実現してみせた、比較的“純粋”なオブジェクト指向システム(言うまでもなく、クラス指向の意味で)だと考えています。他方で Ruby は、セマンティックスにおいてメッセージ指向を大事にしていますが、それにこだわってはいません。しかし、Java に比べればはるかにメッセージ指向よりの言語だと言って差し支えないでしょう。


くだんの「10 のコト」も、Java のクラス指向的立場から見た、Ruby のメッセージ指向的側面のメリット、デメリットという色分けをするととてもすっきり整理できて、語弊もすくなく楽しめるのではないかと思います。