【问题标题】:Instance variable still references after 'dup''dup' 后仍引用实例变量
【发布时间】:2012-01-31 06:23:57
【问题描述】:

我有一个类的对象,我想用dup 复制它。其中一个实例变量是一个数组,它似乎正在引用它。我以为 dup 实际上创建了一个 DUPLICATE。

这是我的 IRB 会话:

irb(main):094:0> class G
irb(main):095:1> attr_accessor :iv
irb(main):096:1> def initialize
irb(main):097:2> @iv = [1,2,3]
irb(main):098:2> end
irb(main):099:1> end
=> nil

irb(main):100:0> a=G.new
=> #<G:0x27331f8 @iv=[1, 2, 3]>

irb(main):101:0> b=a.dup
=> #<G:0x20e4730 @iv=[1, 2, 3]>

irb(main):103:0> b.iv<<4
=> [1, 2, 3, 4]
irb(main):104:0> a
=> #<G:0x27331f8 @iv=[1, 2, 3, 4]

我希望a 保持不变,因为dup 创建了一个全新的变量,而不是引用。

另请注意,如果您要将[1,2,3] 替换为G::initialize 中的标量,dup 将不会引用它。

【问题讨论】:

    标签: ruby dup


    【解决方案1】:

    dupclone 的默认实现只是做一个浅拷贝,所以你会有两个对象引用同一个数组。要获得您想要的行为,您应该定义一个initialize_copy 函数(由dupclone 调用):

    class G
      attr_accessor :iv
      def initialize_copy(source)
        super
        @iv = source.iv.dup
      end
    end
    

    那么这两个对象将引用两个不同的数组。如果数组中有可变对象,您可能想要更深入,dup 数组中的每个对象:

    def initialize_copy(source)
      super
      @iv = source.iv.collect &:dup
    end
    

    【讨论】:

      【解决方案2】:

      dup crates a shallow copy;实例变量引用的对象不会被复制。

      规范的(例如,Really Easy)深拷贝黑客是编组/解组,这在您的实际用例中可能有效,也可能无效(假设这是一个简化的示例)。如果没有,或者编组效率低下,initialize_copy 路由是更好的选择。

      pry(main)> a = G.new
      => #<G:0x9285628 @iv=[1, 2, 3]>
      pry(main)> b = a.dup
      => #<G:0x92510a8 @iv=[1, 2, 3]>
      pry(main)> a.iv.__id__
      => 76819210
      pry(main)> b.iv.__id__
      => 76819210
      pry(main)> b = Marshal::load(Marshal.dump(a))
      => #<G:0x9153c3c @iv=[1, 2, 3]>
      pry(main)> a.__id__
      => 76819220
      pry(main)> b.__id__
      => 76193310
      

      【讨论】:

        【解决方案3】:

        覆盖dupclone 方法:

          def dup
            Marshal::load(Marshal.dump(self))
          end
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-06-18
          • 1970-01-01
          • 2010-12-15
          • 2017-05-18
          • 1970-01-01
          • 1970-01-01
          • 2020-11-01
          相关资源
          最近更新 更多