ゆとりーなの日記

日記的な事を書いて行くと思はれる

実はList list = new ArrayList();ってしっくりこないんです!

 最近ちらほらと話題になっている、

List list = new ArrayList();
ArrayList list = new ArrayList();

ですが、私はどうも前者の書き方がしっくりこないんですね。ある程度の経験があれば、ごく普通のことだと言われているみたいですが、前者を支持する意見をみてもどうなんだろうって思うところがあるわけです。
 まず最初に見かけた理由がこれなんですが、

List list = new ArrayList();
// にしておけば
List list = new LinkedList();
// に変更しても影響が少ない

これがまずしっくりきません。

ArrayList list = new ArrayList();
// を
LinkedList list = new LinkedList();
// に変更するのも手間はそれほど変わらない気がする

 上のパターンと比べても、変更箇所は殆ど変わりません。newする型のついでに変数の型名も変えてしまえばいいだけです。


 次にみかけた理由が、ArrayListよりも優れたSuperListクラスが登場して、これがArrayListを継承してなかったらどうするのという意見です。しかしそれを言い出したらSuperListクラスがListを継承してなかったらどうするのって話になってイタチごっこな気がします。


 そして次に出てくるのが、もしそのSuperListクラスがListを継承していたとします。その時ArrayListで受けていた場合、ArrayList固有のメソッドの部分を根こそぎ探して修正しなければいけないだろうという意見です。
 これもどうなんだろうと思っていて、ArrayList固有のメソッドを使っていたということは既にArrayListの持つインターフェイスが必要だった事例だったということで、わざわざ上に登ってインターフェイスの少ない別の実装(例え他の部分がArrayListより優れていたとしても)に切り替えることがいいことなのか疑問です。逆にこの様な事態に備えてArrayListのメソッドが使えたら便利だけど、将来Listを継承してArrayListを継承していない素敵なサムシングListが来るかもしれないからListのインターフェイスだけに縛っておこうって選択に意味があるのかが疑問なわけです。


 個人的にはListで受けるってことは、今回はListのインターフェイスだけで事足りていて、Listの持つ最低限の約束さえ守ってくれればあとはよりよい実装の物にどんどん変わっていくよっていう決意表明のように思えるんですね。となると、ここにnew 具象クラスの型名();ってやるのは数値リテラルをソースに埋め込むマジックナンバーならぬマジックタイプなサムシングをやってしまってるように感じられるんですね。
 というわけで個人的にはこの様な場合は、newする型名を直接書かずに適当にリスト生成メソッドに切り出してしまった方がいい気がするんです(恐らくこれはprivateでstaticなメソッドになるかと思います)。

private static List createListImpl() {
  return new ArrayList();
}

 こうしておけば、生成メソッドの中身を変えるだけで、リストの実装を切り替えることが出来ますし、且つリストの実装の型情報がどこいにあるんだろうと思ったときにも探しやすいような気がするんですね。
 
註:この話の元ネタは多分Javaの話だと思われますが、私はJava初心者であるので全然見当違いな事を言っている可能性があります。