Ruby:对象深度复制

时间:2012-12-31 17:43:48

标签: ruby deep-copy

我正在研究一些在Ruby中深度复制对象的技术(MRI 1.9.3) 我遇到了以下示例,但我不确定#dup方法实现。 我测试了它并且它确实有效,但是我不理解该方法的逻辑步骤,因此我在自己的代码中使用它并不舒服。

声明@name = @name.dup是否指的是副本中的iVar ?怎么样?我看不到它。

请问有人解释一下吗? 还有,有更好的方法吗?

class MyClass
  attr_accessor :name

  def initialize(arg_str)   # called on MyClass.new("string")
    @name = arg_str         # initialize an instance variable
  end

  def dup
    the_copy = super        # shallow copy calling Object.dup
    @name = @name.dup       # new copy of istance variable
    return the_copy         # return the copied object
  end
end

2 个答案:

答案 0 :(得分:6)

这是一个非常薄的,非常具体的“深层复制”实现。它所展示的是在克隆中创建一个独立的@name实例变量,以便修改具有就地操作的实例的名称不会产生更改克隆的副作用。

通常,深层复制操作对于嵌套数组或散列等内容非常重要,但它们也适用于具有引用该类事物的属性的任何对象。

在你的情况下,要使用更健壮的dup方法创建一个对象,你应该对每个有问题的属性调用dup,但我认为这个例子有点破碎。它的作用是用原件替换原件中的@name,这可能会破坏您的任何参考。

更好的版本是:

def dup
  copy = super
  copy.make_independent!
  copy
end

def make_independent!
  instance_variables.each do |var|
    value = instance_variable_get(var)

    if (value.respond_to?(:dup))
      instance_variable_set(var, value.dup)
    end
  end
end

这应该具有复制支持dup方法的任何实例变量的效果。这会跳过数字,布尔值和nil等无法复制的内容。

答案 1 :(得分:0)

执行super时,实例方法@name将在原始方法和副本之间共享。通过执行@name = @name.dup,原始文件获取字符串的新实例@name,最终与重复实例具有不同的@name