Re: 型宣言は汎用的にすべきか?

型宣言は汎用的にすべきか?』の続き。

コメントより:

とりあえずodzさんの日記を読んでください
http://d.hatena.ne.jp/odz/20080307/1204898914

http://d.hatena.ne.jp/kwatch/20080308/1204939689#c1204952304


リンク先のエントリ、読ませていただきました。しかし、「ローカル変数の場合はキャストしないほうがいい」とまで言いきる根拠はわかりませんでした。「キャストしてもいいし、しなくてもいい (どっちでもいい)」ということならわかるのですが。


そもそもの発端となったのはこれのようですが、

Map map = new HashMap();
HashMap map = new HashMap();
この場合はあんまりありがたみがないのだが,

Point2D point = new Point2D.Float(0f, 0f)
Point2D.Float point = new Point2D.Float(0f, 0f)
この場合は,後者の方がいい.

理由は,Point2D#setLocation(float,float)が使えるからで,最後の最後までPoint2Dにキャストしない方が得策だ.

もちろん例外はある,しかし実際は副作用がないことが多いはずだ.

C#などの言語に型を書かなくて済むvarがあるのが,それを示している.

航海日誌(2008-03-04): 静的型付け言語で,型は最後にダウンキャストしろ


#『Point2D#setLocation(float,float)が使える』は『Point2D.Float#setLocation(float,float)が使える』の間違いでしょうか。

この場合、#setLocation(float,float) を使う必要があるなら Point2D にキャストしないのは当然ですけど、それを使わない場合であればキャストしようがしまいが、どっちでもいいと思います。
ですから、キャスト先の型にないメソッドを使いたいのならキャストしないのは当たり前であり、それをもって、キャスト先の型にあるメソッドだけで済む場合 (例: List や Map の場合) も含めて「キャストしないほうがよい」というのはおかしくないでしょうか。


というかですね、『ローカル変数の型宣言はできる限り特定しておいたほうがよい』って、Java の精神を真っ向から否定してません? Java は interface を使うことで、型に関してなるべく疎結合にすることが推奨されてますよね。それと真反対のことを Java な人がおっしゃるのはちょっと驚きました。どうなんでしょう。


例をあげておきます。後者より前者のほうが型に関して疎になっているので、Java では前者のほうが推奨されているスタイルのはず。

// Reader であればなんでもよい。よって例えば BufferedReader を
// 使うように変更してもよいことがよくわかる。
Reader reader = new FileReader('foo.txt'));

// あえて FileReader に限定している。BufferedReader などに変更して
// いいかどうかは、他の箇所も調べて判断しないといけない。
FileReader reader = new FileReader('foo.txt'));

int ch;
while ((ch = reader.read()) >= 0) {
    System.out.println((char)ch);
}


個人的には「ローカル変数は寿命が短いからあまり気にせず、どっち使ってもいいんじゃね?」と思っていますが、「ローカル変数では型はできる限り特定しておいたほうがいい」という意見はちょっと納得がいきません*1。もちろん、FileReader 固有のメソッドを使う場合は後者になりますが、それはまた理由が違いますよね。

*1:キャストしないほうが速いからとかいう理由がもしかしたらあるかもしれませんが、それはリンク先のどのエントリにも書かれていませんよね?