-JSR245でAPIが抽象クラスな理由
MLに「APIを抽象クラスにしてるのはどうかな、インターフェイスにしてほしい」と投稿していた件、返事が。将来API(未来のJSR)でコンクリートメソッドを追加したいときに、古いAPI(つまりはJSR245)で作ったアプリケーションが問題なく動作するようにですって。うーん、そりゃそうだが、将来コンクリートメソッドを追加しなくてもよいと思うんですよ。たしかに今回インターフェイスで定義したら、そこにメソッド追加すると過去バージョンのインターフェイスで作ったバイナリはクラッシュしちゃうけど。。。
Eclipseの解決方法のほうがスマートだと思います。Eclipseは多くのAPIをインターフェイスで定義して、拡張したいときには、拡張部分を別インターフェイスに定義します。たとえば以下のような感じです。
public interface ISomeSpecification { void someMethod(); }
というオリジナルのAPIがあったとき、
public interface ISomeSpecification2 { void anotherMethod(); }
というのを将来バージョンでは定義します。すると、利用側は、
void userCode(ISomeSpecification someSpecification) { if(someSpecification instanceof ISomeSpecification2) { ((ISomeSpecification2)someSpecification).anotherMethod(); } }
これでいいんじゃないかなとも思うけど、たしかに抽象クラスでやると、次のように違う。
public abstract class ISomeSpecification { public abstract void someMethod(); }
というオリジナルのAPIがあったとき、
public abstract class ISomeSpecification { public abstract void someMethod(); public void anotherMethod() { // additional procedure... } }
というのを将来バージョンで定義しなおします。すると、利用側は、
void userCode(ISomeSpecification someSpecification) { someSpecification.anotherMethod(); }
と普通に呼べる。でもどうかな〜。そうなると将来バージョンではAPIにコンクリートメソッドが入っちゃう。これがJSR245だけでなく、JSF1.1のApplicationなどが抽象クラスで定義されている理由だとスペックリーダーがいうのだけど。。。返事する前に、一晩ぐらいは考えてみよう。