Ruby 对象赋值和指针

Ruby 对象赋值和指针,ruby,object,copy,variable-assignment,Ruby,Object,Copy,Variable Assignment,我对Ruby中的对象分配和指针有点困惑,编写了这个代码片段来测试我的假设 class Foo attr_accessor :one, :two def initialize(one, two) @one = one @two = two end end bar = Foo.new(1, 2) beans = bar puts bar puts beans beans.one = 2 puts bar puts beans puts

我对Ruby中的对象分配和指针有点困惑,编写了这个代码片段来测试我的假设

class Foo
    attr_accessor :one, :two
    def initialize(one, two)
        @one = one
        @two = two
    end

end

bar = Foo.new(1, 2)
beans = bar

puts bar
puts beans

beans.one = 2
puts bar
puts beans
puts beans.one
puts bar.one
我假设当我将bar分配给bean时,它会创建对象的副本,修改一个不会影响另一个。唉,输出结果却显示了另一种情况

^_^[jergason:~]$ ruby test.rb 
#<Foo:0x100155c60>
#<Foo:0x100155c60>
#<Foo:0x100155c60>
#<Foo:0x100155c60>
2
2
这将产生以下不可靠的输出:

foo is 012345
baz is 012345
foo is 01234
baz is 01234
foo is 01234a hill of beans is a wonderful thing
baz is 01234

这让我心烦意乱。在foo上调用pop也会影响baz,因此它不是一个副本,但将某些内容连接到foo上只会影响foo,而不会影响baz。那么,我什么时候处理原始对象,什么时候处理副本?在我自己的课堂上,我如何确保作业是复制的,而不是指针?帮助这个困惑的家伙。

+
-
数组中
每个都返回新的数组,并填充各自的内容,因此
foo+=[…]
不影响
baz
是正常的。试试
这个问题有很多问题。主要要知道的是赋值从不在ruby中复制,但是方法通常返回新对象,而不是修改现有对象。对于Fixnums等不可变对象,可以忽略此项,但对于Array或Foo实例等对象,要创建副本,必须执行
bar.dup


对于数组示例,
foo+=
没有连接到存储在
foo
中的数组上,为此,您可以执行
foo.concat(['a'])
。相反,它正在创建一个新数组,并将
foo
分配给该数组。Array类的文档中提到了哪些方法对数组进行了适当的修改,哪些方法返回了一个新数组。

基本上ruby使用的是引用指针,因此当您更改一件事情时,另一件事情也会受到影响

你从不处理副本。它在内存中是同一个对象,但您只声明了对它的两个引用:在第一个示例中:bar和bean指向内存中的同一个对象;在第二个示例中:foo和baz最初指向内存中的同一个数组

查看Java教程页面中的2张图片/图纸,该页面解释了该机制(与Ruby中的相同),这2张图片仅限于此,比任何文字解释都更有价值:

那么我该如何在我自己的类中实现.clone功能呢?在Foo中实现clone只会返回
Foo.new(self.one,self.two)
在这种情况下,继承的
Object#clone
也可以工作,因为它也复制实例变量。
Object#dup
如果您不想冻结对象的话
foo is 012345
baz is 012345
foo is 01234
baz is 01234
foo is 01234a hill of beans is a wonderful thing
baz is 01234