標準クラス・モジュール > Object > clone, dup
obj.clone obj.dup
clone
メソッドとdup
メソッドは、レシーバのオブジェクトのコピーを作成して返します。オブジェクトのコピーとは、同じ内容を持つ別のオブジェクトです。具体的には、元のオブジェクトと同じクラスの新しいオブジェクトで、元のオブジェクトのインスタンス変数を新しいオブジェクトにコピーしたものです。
clone
メソッドとdup
メソッドはインスタンス変数のコピーを行ったあと、initialize_copy
メソッドを呼び出します。
次の例では、Cat
クラスのオブジェクトoriginal
をコピーしたオブジェクトcopied
を作成しています。別のオブジェクトなのでequal?
メソッドの結果はfalse
になります。また、インスタンス変数@name
がコピーされていることがわかります。
class Cat attr_accessor :name def initialize(name) @name = name end end original = Cat.new("Tama") copied = original.clone puts copied.equal?(original) puts copied.name
false Tama
clone
メソッドとdup
メソッドは同じ働きをしますが、次の違いがあります。
clone
メソッドはオブジェクトの凍結状態、汚染状態、信頼状態をコピーする。dup
メソッドは汚染状態と信頼状態をコピーするが、凍結状態はコピーしない。clone
メソッドはオブジェクトの特異メソッドもコピーする。dup
メソッドはコピーしない。clone
とdup
は「浅いコピー」を作ることに注意してください。上記のCat
クラスの例では、@name
がoriginal
からcopied
にコピーされますが、@name
が指しているオブジェクト(文字列)は同じものです。copied
の@name
に対して破壊的なメソッド(レシーバ自身を変更するメソッド)を呼び出すと、original
の@name
が指している文字列も変更されます。
copied.name.replace("Mike") puts original.name
Mike
インスタンス変数の参照先まで「深いコピー」を作るには、自作のクラスでclone
とdup
を上書きするか、initialize_copy
メソッドを定義します。
コピーできないオブジェクト(true
、false
、nil
、シンボル、数値)に対してclone
やdup
を呼び出すと、例外TypeError
が発生します。
initialize_copy
: オブジェクトをコピーするときに呼ばれる。