Java7で待望のプロパティ構文が採用される様子ですが、このプロパティにまつわる問題と歴史を見てみましょう。
Javaが出た当初
Javaのクラスにはフィールド(C#で言うメンバ変数)とメソッド(同、関数)が持てます。
もともと、Javaではpublicなフィールドというものも忌避されてはおらず、
当初はsetter,getterというアクセッサを用意するというスタイルではありませんでした。Javaが出た当初の1995年前後の話です。
例えば、古くからあるクラスのひとつとして
java.awt.Pointクラスがあります。
これは2次元平面上の座標を表すクラスですが、publicなフィールドとしてxとyがあります。
そしてこの可変なフィールドに対してsetメソッドは用意されていません。
getX()、getY()は存在しますが、doubleの精度で返すというsetter,getterとは違う目的のメソッドとなっています。
しかし、publicフィールドでは読み込みと書き込みの2つを分けてアクセス権を設定することができませんでしたし、
フィールドアクセスに対して同期をとることもできませんでした。
隠蔽の観点からはフィールドをそのままpublicとして公開することはどうも得策ではない、というのは急速に知られるようになったわけです。
privateなフィールドを作り、publicなメソッドとしてsetter,getterを用意するというスタイルが定着し始めたのは
1997年後半にJava Beansの仕様が提示された後のことです。本来、Java Beansは再利用可能なソフトウェアコンポーネントを目指して
制定されたのですがあまりそちら方面の活躍は芳しくなかった覚えがあります。
Java Beansではsetter,getterスタイルであることが要求されたため、次第にこのスタイルが定着していきました。
これは、publicフィールドに対する、現実解のひとつでしたが、当然煩わしいものとなってしまいました。
IDEによる自動生成サポートなどで負担は軽減されましたが、Javaの言語設計の中でも失敗点に数えられます。
Javaへプロパティ構文が導入しにくい理由
メソッドは、そのメソッド内部で処理を追加することで、すべてのアクセスに対してなんらかの処理を行うことが容易にできます。
デバッグに際してメソッドの先頭に開始を出力するSystem.out.print()を書いたりasert文を書いたりした人も多いことでしょう。
フィールドへのアクセスは、その前後に処理を追加するようなことができません。
これは、アスペクト指向的な話題、つまりすべてのアクセスに対してなんらかの処理が追加となった際に、
フィールドアクセスに対してはなんらの効率的な手段をもたないことを意味します。
実際、フィールドアクセスに対してSystem.out.print()することができません。
こうした、アスペクト指向でいうジョインポイントを確保するという意味でもpublicフィールドを扱う設計はよろしくない。
さて、プロパティ構文の導入にあたって、見ための構文はともかく、内部的にはメソッドコールに置き換えてやる
必要性があるということになります。これはsetter,getterのアクセス権の切り分けなどが理由ですね。
ところが、JavaVMのバイトコードからしてフィールドアクセスとメソッドアクセスは違っており、
フィールドの取得はgetfield命令ですし、メソッド呼出しはinvokevirtual命令およびinvokespecial命令です。
ですから、あるクラスのフィールドを内部的にメソッドにしてしまうような手法では、そのクラスを参照しているすべての
getfield命令がinvoke命令に変えられなければならず、最低でも再コンパイルが必要になってしまいます。
こうした事情から、Javaにプロパティ構文を載せることは難儀したようで、C#が2002年に出たにもかかわらず、
2008年のリリースが予定されるJava7まで随分と時間がかかってしまいました。
既存のリソースとの接合という難作業を行ったワークグループの神業に惜しみない賞賛を送りたいと思います。
(Java5.0で追加になったジェネリクスも神業と言えますね)
フィールドとメソッドを同一視すると…
クラスはフィールドとメソッドを持ちますが、例えばC#のように関数ポインタのようなものがある場合、
メソッドもつまるところ関数型のフィールドと言えてしまう。
こうした形態の最たるものがJavaScriptなどに代表されるプロトタイプベースのオブジェクト指向言語ですね。
すると、クラスというのはフィールドの配列のようなものということになってしまう。
ただ、フィールドに対して、メソッドの実行呼び出しが面倒なので構文上はシンタックスシュガーとして
簡易にメソッド呼出しができる必要がありますね。
このフィールドアクセスに対して、参照と変更、あるいは実行に対してアクセスレベルを設定でき、
またアスペクトのウィービングが可能であるのであれば、プログラム言語としてはすっきりとした仕様になるように思います。
メソッドに継承階層を持たせることを可能とすると、動的にメソッドの内容を差し替えられる静的言語が可能となります。
静的型付けであるにはクラスが保持するフィールド・メソッドの型が同じである必要がありますが
型が同じであればメソッドを切り替えることができてしまう。null値の考慮が入りますが、型の代入互換性は保てるのです。
そのような言語を考えてみるのも楽しそうですね。
投稿日時 : 2008年5月7日 21:27