【问题标题】:Ruby: object deep copyingRuby:对象深度复制
【发布时间】:2012-12-15 18:52:52
【问题描述】:

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

声明@name = @name.dup 指的是副本inside 的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

【问题讨论】:

标签: ruby deep-copy


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    这是“深拷贝”的一个非常精简、非常具体的实现。它演示的是在克隆中创建一个独立的@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 等内容。

    【讨论】:

      猜你喜欢
      • 2018-01-28
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2012-07-03
      • 2014-11-03
      • 2016-07-07
      • 1970-01-01
      • 2015-01-08
      相关资源
      最近更新 更多