[2106] Re:リストA-13の ”~Impl” について
投稿者:(ぱ)こと管理人
2018/02/18 13:16:18
>せっかく抽象型を用意しているのであれば、ここは抽象型の変数定義にするのではと
>思ったのですが、サブクラスの変数定義を使用している理由があれば、
>教えて頂きたいです。
これは私の流儀であって、Javaでの一般的な書き方かというとそうでもないかも
しれませんが、私は、Javaでパッケージを分ける規模のプログラムを書くときは、
パッケージ単位でインタフェースと実装を分けるようにしています。
たとえばHttpServletRequestクラスであれば、インタフェースを
com.kmaebashi.henacat.servletに、実装を
com.kmaebashi.henacat.servletimplに置いています。
そして、HttpServletRequestの利用者(この場合はサーブレットのプログラムを書く人)
にはインタフェース側だけをimportしてもらうようにします。Cookieのような
簡単なクラスを除き、インタフェース側のパッケージには実装は置きません。
こうすることで、利用者にとっては、インタフェース側のパッケージは
ほぼAPIドキュメントのようなものになりますし、実装が「作りかけ」の
状態でも、利用者側のプログラムのコンパイルまではできるようになったりします。
公式のサーブレットAPI(javax.servlet)も、利用者には(Cookieのような
簡単なクラスを除き)ほぼインタフェースしか公開していないのは、
同じような考え方に基づくものだと私は思っています。
こういう観点でインタフェースと実装のパッケージを分けているわけですが、
そう考えたとき、実装側のパッケージ内でインタフェースの方の型で変数定義
することに、どれほどの意味があるでしょうか。
実装側のパッケージ内では、インタフェースとしては公開していないメソッドや、
publicではないフィールドを参照することもあり得ます。そのたびにダウンキャスト
するぐらいなら、最初から実装側のクラスにしておくほうがマシではないかと思います。
servletimplという実装側のパッケージの内部で、むやみに実装隠蔽しようとしても
あまり意味はないかと思います。Javaのアクセス制御が、publicもprivateも
つけないデフォルト状態で、(C++やC#と違って)パッケージ内公開になっている、
というポリシーも、「パッケージ内での実装隠蔽はあまり意味がない」という
考えに基づくものではないでしょうか。