Объектное присвоение и указатели

Я немного смущен объектным присвоением и указателями в 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

Я предположил, что, когда я присвоил панель бобам, она создаст копию объекта, и изменение того не влияло бы на другой. Увы, вывод показывает иначе.

^_^[jergason:~]$ ruby test.rb 
#<Foo:0x100155c60>
#<Foo:0x100155c60>
#<Foo:0x100155c60>
#<Foo:0x100155c60>
2
2

Я полагаю, что числа имеют некоторое отношение к адресу объекта, и они - то же для обоих бобов и панели, и когда я изменяю бобы, панель изменяется также, который не является тем, что я ожидал. Кажется, что я только создаю указатель на объект, не копию его. Что я должен сделать для копирования объекта на присвоении, вместо того, чтобы создать указатель?

Тесты с классом Массива показывают некоторое странное поведение также.

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}"

Это производит следующий вывод wonky:

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

Это уносит мой ум. Вызов поп на нечто влияет на baz также, таким образом, это не копия, но конкатенация чего-то на нечто только влияет на нечто, и не baz. Таким образом, когда я имею дело с исходным объектом, и когда я имею дело с копией? В моих собственных классах, как я могу удостовериться, что присвоение копирует, и не делает указатели? Выручите этого смущенного парня.

6
задан jergason 14 April 2010 в 05:52
поделиться

2 ответа

В этом вопросе много вопросов. Главное, что нужно знать: присваивание никогда не создает копию в ruby, но методы часто возвращают новые объекты вместо изменения существующих объектов . Для неизменяемых объектов, таких как Fixnums, вы можете игнорировать это, но для таких объектов, как массивы или экземпляры Foo, чтобы сделать копию, вы должны сделать bar.dup .

Что касается примера массива, foo + = не объединяется с массивом, хранящимся в foo , для этого вы должны сделать foo.concat (['a ']) . Вместо этого он создает новый массив и присваивает ему foo . В документации для класса Array упоминается, какие методы изменяют массив на месте, а какие возвращают новый массив.

11
ответ дан 8 December 2019 в 14:41
поделиться

+ и - в Array каждый возвращает new массивы, заполненные соответствующим содержимым, поэтому foo += [...] не влияет на baz - это нормально. Попробуйте использовать оператор << на foo, и в результате baz получит такое же изменение.

Я не уверен, как Ruby обрабатывает другую вещь внутри, но вы можете попробовать использовать one.clone и two.clone в Foo#initialize.

3
ответ дан 8 December 2019 в 14:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: