IT-PRESSこの広告は、90日以上更新していないブログに表示しています。この本の項目11に、「cloneを注意してオーバーライドする」というセクションがある。そのほかにも、Javaのcloneメソッドは各所で嫌われているようだ。そのような論調において、clone代替案としては、コピーコンストラクタと、staticなファクトリメソッドがしばしば挙げられる*1。うん、確かにJavaのcloneメソッドはイケてない。イケてない理由はみんなと同じだから上記の各文献を当たってください。要するに「きちんと実装するのが難しく、それをコンパイラに強制させられない」のです。言われれば、俺はNOだ。要件として「コピー元と同じ実装クラスのインスタンスを生成しなければならない」というケースでcloneを使わざるを得ない場合がある。コピーコンストラクタは、コピー元の実装クラスを知らなければ使えない。staticなファクトリメソッドも、オーバーライドが出来ないため、やはりコピー元の実装クラスを知る必要がある。言いたいことはだいたい伝わったとは思うのだが、具体例で説明してみたい。...で、これを説明するにあたって、良く知られたクラスを例に出したかった。そんな例が見つからなかった...。不当に嫌われすぎていて、そんな実装例が見つからないのだ*2。いうわけで、現実の話を少し曲げて説明に使ってみる。JavaにはListというインターフェイスがあって、その実装としてArrayListやLinkedListがある。インターフェイスを実装しておらず、ArrayListとLinkedListはこれを実装しているということ。これは何故だろう、と考えると、ArrayListやLinkedListは、順序付き集合をオンメモリで扱う実装だからだ。メモリ上の集合ならばcloneしても構わない。Listはというと、実装がオンメモリであるとは限らない。add/removeなどを実行する度に、律儀にファイルやDB、もしくはリモートのサーバに内容を書き出すような実装クラスを作っても、Listインターフェイス契約的には何ら問題にならない。List型にcloneを認めてしまうと、このような実装を妨げてしまうからであろう。ここで、現実の話を少し曲げる。いうインターフェイスを挟んであるものだと仮定する。一つ、ArrayList#clone()も戻り値型はObject型ではなくArrayList型、そしてLinkedList#clone()の戻り値型は同様にLinkedList型である、とします。