- - PR -
java.util.Collection のメソッドがサブインターフェースの List にもあるのはなぜ?
| 投稿者 | 投稿内容 | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2003-11-28 09:53
unibon です。こんにちわ。
Java2 の Collections API を見てて、 メソッドや型階層に冗長さがあることが気になっています。 (1) Java2 の java.util パッケージにおいて、 Collection インターフェースはつぎのように 15 個のメソッドを持ちます。
このサブインターフェースである List は つぎのように 25 個のメソッドを持ちます。
その内の 15 個は Collection がすでに持っているものです。 というか Collection が持っている 15 個のメソッドすべてを List が再度持ち直しています。 なぜこのように冗長にしているのでしょうか。 コードを書く上でこうすべきなのでしょうか。 それとも型階層をブラウズする際にスーパクラスを何段も遡らなくて済むように、 余計な配慮かなにかのためでしょうか。 (2) また、もうひとつの類似の疑問としては、 つぎのように、ArrayList は AbstractList のサブクラスですが、 List も implements しています。
しかし、つぎのように AbstractList の段階ですでに List を implements しています。
したがって、ArrayList が List を implements する必要はなく、冗長だと思います。 上記(1)はメソッドの冗長さでしたが、こんどは型の冗長さになっています。 おそらくこれらのアーキテクチャになった背景の考えかたは(1)も(2)も同じなのでは と推測しますが、この推測は合っているでしょうか。 | ||||||||||||||||
|
投稿日時: 2003-11-28 10:08
全くの推測ですが・・・ JavaDocを出力するためとか? | ||||||||||||||||
|
投稿日時: 2003-11-28 11:09
設計した本人でないと分からないと思いますが、憶測で・・・。まぁ、眉につばをつけつつ読んでください。
おそらく、List と Collectionの概念の違いのためだと思います。Collectionはフレームワークの一番基礎となっている部分です。Collectionはとても抽象化されていて、コレクションにオブジェクトをaddしたりするのはListやSetにaddするのとは違う意味を持つような気がします。 Sub-interfaceがSuper-interfaceのメソッドと同じメソッドを宣言するのはOverrideです。つまり、すでに宣言されているメソッドをOverrideすることにより「同じメソッド名だけど実際の意味はちょっと違いますよ」というのを強調している感じがします。意識的にしろ、無意識的にしろ、設計者の意図はそういった概念的なものではないでしょうか。実際SetもCollectionのメソッドをOverrideしています。 2番目の型の冗長ですが、これも概念的なものだと思います。おそらく、ArrayListはそれ自体がListの実装であり、冗長な型宣言をすることでArrayListはListとより近いものであると言っているよう気が私はします。もしArrayListがListを直接implementしなかった場合、ArrayListはAbstractListのサブクラスのような印象を受けますが、冗長的な宣言をすることにより、ArrayListはListであると強調している感じがします。 とまぁ、勝手な想像をしてみました。ここら辺は仕様によって決められていないので個人の概念の考え方で決まっているような気がします。実質的に問題はないですし、私よりもよりオブジェクト指向のエキスパート達が考えたもののはずなので、あまり気にはしませんけどね。 | ||||||||||||||||
|
投稿日時: 2003-11-28 12:32
私も眉唾です。一切の証拠はありません。 ArrayListの設計者(Joshua Bloch ?)はイメージとして、AbstractListは実装のみを継承し、Listからはインターフェースのみを継承するということを言いたいのではないのでしょうか? C++流にかくと class ArrayList : public List private AbstractList { } ってな感じで。残念ながら、Javaにはprivate継承に相当するものがないため、今の形にあたのでは。 「そのクラスを実装の詳細とする」ことに関して、オブジェクトコンポジションという方法もありますが、抽象クラスをインスタンス化することはできないので、はなから却下されたと。 憶測なので、丸々信じないでください。 [ メッセージ編集済み 編集者: かずくん 編集日時 2003-11-28 12:33 ] | ||||||||||||||||
|
投稿日時: 2003-11-28 12:45
実は単に、当初AbstractListはListから実装されていなかった。そのため、 public class ArrayList extends AbstractList implements List.... となった。けど、あとで、AbstractListはListから派生したほうが良いかなとなったが、 もはや、互換性のため、クラス定義を変更することができず、今のままで放置されている。 な〜んてことはまずないわな(あったらコワイ)。 | ||||||||||||||||
|
投稿日時: 2003-11-28 14:14
「私はこうだと思う」論の追加。
AbstractList に限らず、AbstractMap (implements Map) のサブクラス(HashMap など)も改めて implements Map としているところを見ると、単純に 「サブクラス(ArrayList など)の定義だけ見て List インターフェイスを持っていることがぱっと見ですぐわかるから。」 なだけな気がします。 swing の Abstract* ではそうなってないですけどね。 | ||||||||||||||||
|
投稿日時: 2003-11-28 15:10
僕としては、かずくんさんの意見に賛成です。 ただ、もし実装のための継承という意図があったのなら、こうした方がよかったのかな、とは思いますが。
[ メッセージ編集済み 編集者: Emacs信者 編集日時 2003-11-28 15:15 ] | ||||||||||||||||
|
投稿日時: 2003-11-29 10:56
こんなこになってしまったら、AbstractListの実装が不明になってしまい、 効率よいListの作成のためにどのメソッドを記述すべきか分からなくなってしまいますね。 | ||||||||||||||||
