我正在研究一些在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
答案 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
。