前置き
なんか「イマドキ」の言語から見ると Java は古くてイケてないとかいう人がいっぱいいるらしい。
それにたいして、「そうじゃないよ、Java はそもそもからして偉大なる中庸を目指しているのであるからしてこれでいいんだよ」という平生からの私の主張1を『C++の設計と進化』を根拠にゆるーくポエります。
なぜ『C++の設計と進化』なのか?
Java が C++ の影響を受けていることはいうまでもありません。そして、Java には C++ から が選んだもの、選ばなかったものがそれぞれもちろんあります。ストラウストラップがいかにして C++ を作ったかが本人の言葉により語られている『C++の設計と進化』を読むことで、Java がいかにして今の道を選択したかもまた見えてくるのではないかと思います。
それをさておいても、『C++の設計と進化』は C++ ができるできないにかかわらず、「言語なんて動けば何でもいい」という意識の壁を乗り越えた上でプログラミング言語を愛でるプログラマなら誰でも読んでおいて損のない本だと思います。
問題は、もう新品が入手できないことですね。私はこの記事を書くにあたって、久しぶりに図書館で借りて読みました・・・。
『C++の設計と進化』に見る Java の方向性
というわけで、以下の引用は断りのない限り『C++の設計と進化』からのものです。
クラスとインタフェース
Java には class と abstract class と interface があるのはみなさんご存じのとおりですが、それぞれの使い分け、特に abstract class と interface の使い分けについて悩まれる方もいるのではないかと思います。
関数の定義は、ふつうは"よそ"(クラス宣言の外)で指定する。それは、クラスの宣言を(中略)、純粋にインタフェイスの仕様のようにするためである。
Java にあてはめれば、これは class と interface ですよね。interface はまさに「インタフェイスの仕様のようにするため」に用意されたと言えそうです。
インタフェイスと実装を分離するために派生クラスを使うということを、C++のユーザたちに正しく説明しなかった。説明の努力はしたが、どうも趣旨がちゃんと伝わらなかったようだ。この失敗の主な理由はたぶん、多くの(ほとんどの?)C++プログラマやC++に関心を持っているそのほかのプログラマたちが、インタフェイスを指定しているクラス宣言の中に表現ーーオブジェクトの実装の一部ーーを書けることイコールそうしなくてはならないことだ、と考えるとは、私は夢にも想像しなかったからだ。can(できる)がhave to(必ずそうする)に誤解されて、"必ずつねに"表現(実装)をクラス宣言の中に書いてしまったら、私が説明しようとした派生クラスのメリットがなくなるのは当然である。
はい、インタフェースの中に実装も書ける、これは abstract class ですね。
Java のクラスシステムが、実際にストラウストラップの思想に沿う形で設計されたのかどうかは分かりかねますが、仮にそうだとすれば設計を interface で行い実装を class で行えばよいことになり、abstract class は特に必要がなかったのではないかと考えることも可能かと思います。
しかし Java は、C++ が結果として持ってしまった「インタフェイスを指定しているクラス宣言の中に表現ーーオブジェクトの実装の一部ーーを書けること」という部分を敢えて abstract class として持つことを選択したように思えます。
abstract class を持たないという選択肢もあったように思うのですが、Java はそれをあえて持ったのです。
C++ が C をベースにした理由
Cとの違いを大きくしなかった理由は、いくつかある。Cのシステムズプログラミングへの適正と、Simulaのプログラム組織化能力を一体化すること自体が、大きなチャレンジだった。そのほかの言語の重要な機能を次々を加えていったら"ショッピングリスト"言語になってしまい、焦点の定まらない言語が出来上がっただろう。
CやSimulaの実装済みの技術を最初から無視していたら、C with ClassesとC++の成熟はもっと長くかかったことだろう。
これらは、恐らく言語実装上の話だと思いますが、言語仕様の話としても、すでにあるものをあえて変えずにいることは普及にとっては大きな意味があったのではないでしょうか。
シンタクス
私が一番嫌いなCのシンタクスは、宣言のシンタクスだ。宣言用の演算子に前置型と後置型の両方があるので、多くの人を混乱させる。
この部分の変更に対するユーザからの否定的な反応は、非常に強かった。
Java でも、例えば配列の宣言は
String[] values = null;
この表記が推奨されていますが
String values[] = null;
変数の方に []
を付けても大丈夫ですし
なんだったら
// 空白なしでも
String[]values = null;
// 変数の頭にくっついても
String []values = null;
// スカスカでも
String [] values = null;
// 改行しても
String values
[] = null;
これらも全て認められているわけです。
これまた、最初の表記だけを認めるという選択も当然あったかとは思うのですが、Java はそれを選びませんでした。ストラウストラップが C++ でやろうとしてできなかったシンタクスの変更を Java もまた、しないことを選んだのです。
あとがき
ほかにも、プリミティブ型の存在や OOPL として純粋とはいえないなど、何故?と言いたくなるような部分はいろいろあろうかとは思いますが、きっと Java は全部わかっていてそれを選んでいるのです。
どこまでもどこまでも、尖らず中庸であり続けるために。
そんな Java が私は大好きです。
-
私が勝手にそう思っているだけですよ ↩