Object#cloneがshallow copyな理由

投稿者: | 2006年11月21日

 RubyのObject#cloneがdeep copyしない理由は簡単。相互参照がある場合や、コピーできないものを内包していた場合の挙動をグローバルに(Object/Kernelで)定義するのが難しいから。

 もっと利用側寄りの理由としては、deep copyされたくないケースも多いから。特に、ArrayやHashのように何でも入れられるコンテナオブジェクトが、dup/cloneで各要素をdup/cloneして回るべきかと言われると躊躇する。コネクションオブジェクトやソケット、ファイルハンドルもdupする?

 一方、メンバの参照コピー(shallow copy)で足らない部分は、適宜自分のクラスのinitialize_copyメソッドで定義できる。たとえばメッセージダイジェストを計算するオブジェクトなら、内部ベクタなどについては”deep copy”する。でないと、クローンを操作したらコピー元の値や状態まで変わった、ということになってしまう。何をdeep copyすべきかというのは各オブジェクトが知っており、自分が固有に持つものについては自分が責任を持ってコピーする。

 Perlは文字列や配列がオブジェクトでないので、文字列の配列などは単なる代入によって実質deep copyになる。その辺が感覚の違いを生むのだろう。

 ちなみに、Rubyで手軽にdeep copyしたければMarshal.load(Marshal.dump(obj))が定石。これはPerlのStorable::dclone(obj)と等価。

カテゴリー: Tech

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です