如何理解#dup和#clone对引用其他对象的对象进行操作?

时间:2013-04-24 13:10:03

标签: ruby object clone dup

我不确定“的含义......但不是rubyrubinus的文档中它们引用的对象

ruby-doc中,有#clone#dup行为的解释说:

  

生成obj的浅表副本 - obj的实例变量   复制,但不是他们引用的对象。复制冷冻和   被污染的状态另见Object#dup。

下的讨论

Rubinius

的实施中重复了同样的事情
  

复制实例变量,但不递归复制对象   他们参考。复制污点。

我尝试使用以下代码,但行为超出了我的预期。

class Klass
   attr_accessor :array
end

s1 = Klass.new
ar = [1, 2, 3]
s1.array = [ar]

s2 = s1.clone
# according to the doc,
# s2.array should be initialized with empty Array
# however the array is recursivley copied too

s2.array.equal? s1.array # true

2 个答案:

答案 0 :(得分:3)

在Ruby中,所有对象都是引用。看一下下面的例子:

class Klass
  attr_accessor :a
end

s1 = Klass.new
a = [1,2,3]
s1.a = a
s2 = s1.clone
s1.a.object_id  #=> 7344240 
s2.a.object_id  #=> 7344240 

您可以看到两个数组都是同一个对象,并且它们都是引用到堆中某处的数组。在深层副本中,数组本身将被复制,而新的s2将拥有自己的不同数组。数组不会被复制,只是被引用。

注意: 如果您进行深层复制,这就是它的样子:

s3 = Marshal.load(Marshal.dump(s1)) #=> #<Klass:0x00000000bf1350 @a=[1, 2, 3, 4], @bork=4> 
s3.a << 5 #=> [1, 2, 3, 4, 5] 
s1 #=> #<Klass:0x00000000e21418 @a=[1, 2, 3, 4], @bork=4> 

答案 1 :(得分:0)

“相等吗?”比较检查它们是否完全相同:

  • ==比较检查两个值是否相等
  • EQL?检查两个值是否相等且类型相同
  • 等于?检查两件事是否是同一个对象。

例如:

a=[1,2]
=> [1, 2] 
a == [1,2]
=> true 
a.eql? [1,2]
=> true 
a.equal? [1,2]
=> false 
a.equal? a
=> true

当您使用相同的测试时?它显示副本没有创建一个未初始化数组的对象,但它使复制的对象指向与原始数组相同的数组。如果以递归方式复制opjects,则s2.array将具有与s1.array相同的内容,但是它将是一个不同的对象,所以:

s2.array.equal? s1.array # false
s2.array.eql? s1.array # true