配列やハッシュなどの要素がStringやIntegerなどであれば、dupメソッド又はcloneメソッドでコピーすれば問題がありません。コピー後の要素を書き替えても、元の配列やハッシュはそのまま維持されます。
しかし、配列やハッシュの要素として例えば配列オブジェクトが用いられている場合に、中の配列オブジェクトを書き替えると、元もコピーも書き替えられてしまいます。これは、オブジェクト全体をコピーしているからでは無く、中の配列オブジェクトを指し示しているという「情報」だけがコピーされているためです。
ということで、元の配列やハッシュの要素が壊れると困る場合には、中の配列オブジェクトも複写した「深いコピー」を行う必要があります。
深いコピーと浅いコピー
clone や dup はオブジェクト自身を複製するだけで、オブジェクトの指している先(たとえば配列の要素など)までは複製しません。これを浅いコピー(shallow copy)といいます。
深い(deep)コピーが必要な場合には、 Marshalモジュールを利用してMarshal.load(Marshal.dump(obj))このように複製を作成する方法があります。ただしMarshal出来ないオブジェクトが含まれている場合には使えません。
obj = ["a","b","c"] obj_d = obj.dup obj_d[0] << "PLUS" p obj #=> ["aPLUS", "b", "c"] p obj_d #=> ["aPLUS", "b", "c"] obj_m = Marshal.load(Marshal.dump(obj)) obj_m[1] << "PLUS" p obj #=> ["aPLUS", "b", "c"] p obj_m #=> ["aPLUS", "bPLUS", "c"]