Rubyリファレンス: Home

clone, dup (Object)

Edit   History

標準クラス・モジュール > 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メソッドは同じ働きをしますが、次の違いがあります。

浅いコピー

clonedupは「浅いコピー」を作ることに注意してください。上記のCatクラスの例では、@nameoriginalからcopiedにコピーされますが、@nameが指しているオブジェクト(文字列)は同じものです。copied@nameに対して破壊的なメソッド(レシーバ自身を変更するメソッド)を呼び出すと、original@nameが指している文字列も変更されます。

copied.name.replace("Mike")
puts original.name
Mike

インスタンス変数の参照先まで「深いコピー」を作るには、自作のクラスでclonedupを上書きするか、initialize_copyメソッドを定義します。

コピーできないオブジェクト

コピーできないオブジェクト(truefalsenil、シンボル、数値)に対してclonedupを呼び出すと、例外TypeErrorが発生します。

関連項目