Atribuição de objetos e ponteiros
Estou um pouco confuso sobre a atribuição de objetos e ponteiros em Ruby, e codifiquei esse trecho para testar minhas suposições.
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
Eu tinha assumido que, quando designasse bar para beans, ele criaria uma cópia do objeto e a modificação de um não afetaria o outro. Infelizmente, a saída mostra o contrário.
^_^[jergason:~]$ ruby test.rb
#<Foo:0x100155c60>
#<Foo:0x100155c60>
#<Foo:0x100155c60>
#<Foo:0x100155c60>
2
2
Acredito que os números tenham algo a ver com o endereço do objeto, e são os mesmos para os beans e bar, e quando eu modifico os beans, a barra também muda, o que não era o que eu esperava. Parece que estou apenas criando um ponteiro para o objeto, não uma cópia dele. O que preciso fazer para copiar o objeto na atribuição, em vez de criar um ponteiro?
Testes com a classe Array também mostram um comportamento estranho.
foo = [0, 1, 2, 3, 4, 5]
baz = foo
puts "foo is #{foo}"
puts "baz is #{baz}"
foo.pop
puts "foo is #{foo}"
puts "baz is #{baz}"
foo += ["a hill of beans is a wonderful thing"]
puts "foo is #{foo}"
puts "baz is #{baz}"
Isso produz a seguinte saída instável:
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
Isso me surpreende. Chamar pop em foo também afeta o baz, por isso não é uma cópia, mas concatenar algo no foo afeta apenas o foo, e não o baz. Então, quando estou lidando com o objeto original e quando estou lidando com uma cópia? Nas minhas próprias aulas, como posso garantir que a tarefa copie e não faça ponteiros? Ajude esse cara confuso.