4

我正在研究一些在 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
4

2 回答 2

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不能复制的内容。

于 2012-12-31T17:50:25.333 回答
0

当您这样做super时,实例方法@name将在原始和副本之间共享。通过这样做@name = @name.dup,原始获得了一个字符串的新实例 as @name,最终@name与重复实例具有的不同。

于 2012-12-31T17:52:36.893 回答