ほんとに Marshal.load(Marshal.dump(obj)) 使うのかなぁ。

実験環境。


$ uname -mrsv
Linux 2.6.26-2-amd64 #1 SMP Tue Jan 25 05:59:43 UTC 2011 x86_64
 
$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux]

サンプルコード。
変数aを変更するとbも変更されてしまう。
Marshal.load(Marshal.dump(obj))すれば大丈夫。


$ cat ./rubystr.rb
#!/usr/bin/env ruby
$KCODE='u'
 
a = 'abcde'
b = a
puts "----------"
puts "a=#{a}"
puts "b=#{b}"
 
a.upcase!
puts "----------"
puts "a=#{a}"
puts "b=#{b}"
 
a = 'vwxyz'
puts "----------"
puts "a=#{a}"
puts "b=#{b}"
 
b = Marshal.load(Marshal.dump(a))
puts "----------"
puts "a=#{a}"
puts "b=#{b}"
 
a.upcase!
puts "----------"
puts "a=#{a}"
puts "b=#{b}"

実行結果。


$ ruby ./rubystr.rb
----------
a=abcde
b=abcde
----------
a=ABCDE
b=ABCDE
----------
a=vwxyz
b=ABCDE
----------
a=vwxyz
b=vwxyz
----------
a=VWXYZ
b=vwxyz
深いコピーと浅いコピー

clone や dup はオブジェクト自身を複製するだけで、オブジェクトの指している先(たとえば配列の要素など)までは複製しません。これを浅いコピー(shallow copy)といいます。

深い(deep)コピーが必要な場合には、 Marshalモジュールを利用して

Marshal.load(Marshal.dump(obj))

このように複製を作成する方法があります。ただしMarshal出来ないオブジェクトが含まれている場合には使えません。

instance method Object#clone
オブジェクト指向プログラミングにおいて、イミュータブル(immutable)なオブジェクトとは、作成後にその状態を変えることのできないオブジェクトのことである。対義語はミュータブル(mutable)なオブジェクトで、作成後も状態を変えることができる。

イミュータブル - Wikipedia

Rubyでは「=」メソッドって定義できないんだっけ?
コピーコンストラクタみたいな。

tags: ruby

Posted by NI-Lab. (@nilab)