class ListArray
attr_accessor :arr
def initialize(arr)
@arr = arr
end
def arr_object_id
@arr.object_id
end
end
Создать экземпляр ListArray
, создав переменную экземпляра @arr
, равную [0, 1, 2, 3]
:
a = ListArray.new [0, 1, 2, 3]
#=> #<ListArray:0x0000574d960e19e8 @arr=[0, 1, 2, 3]>
Давайте проверим значение @arr
и получим его идентификатор объекта:
a.arr
#=> [0, 1, 2, 3]
a.arr_object_id
#=> 47995370802440
Теперь создайте еще один экземпляр ListArray
, создав его переменную экземпляра @arr
и установив его равным значению a.arr
:
b = ListArray.new(a.arr)
#=> #<ListArray:0x0000574d9611bdf0 @arr=[0, 1, 2, 3]>
b.arr
#=> [0, 1, 2, 3]
b.arr_object_id
#=> 47995370802440
Интересная вещь здесьэто то, что a.arr_object_id == b.arr_object_id
.Это не удивительно, поскольку мы инициализировали переменную экземпляра b
переменной экземпляра a
, поэтому это один и тот же объект !
Далее измените значениеПеременная экземпляра a
в [0, 1, 999, 3]
:
a.arr[2] = 999
a.arr
#=> [0, 1, 999, 3]
a.arr_object_id
#=> 47995370802420
Проверьте, изменилось ли значение переменной экземпляра b
:
b.arr
#=> [0, 1, 999, 3]
b.arr_object_id
#=> 47995370802440
Имеет, потому что *Переменные экземпляра 1034 * и b
@arr
содержат один и тот же объект.
Чтобы переменная экземпляра b
содержала массив, переменные экземпляра которого совпадают с a
, но сделайте два массива различными объектами, создайте b
с его переменной экземпляра @arr
, равной копии значения переменной экземпляра a
:
a = ListArray.new [0, 1, 2, 3]
#=> #<ListArray:0x0000574d9610d818 @arr=[0, 1, 2, 3]>
a.arr_object_id
#=> ...320
b = ListArray.new(a.arr.dup)
#=> #<ListArray:0x0000574d961143c0 @arr=[0, 1, 2, 3]>
b.arr
#=> [0, 1, 2, 3]
b.arr_object_id
#=> ...100 (different than a.arr_object_id)
a.arr[2] = 19
a.arr
#=> [0, 1, 19, 3]
b.arr
#=> [0, 1, 2, 3]
Но, подождите, мы еще не закончили.Вот второй пример, который иллюстрирует, почему вы не всегда можете просто применить dup
.
a = ListArray.new [0, [1, 2], 3]
#=> #<ListArray:0x0000574d9614b370 @arr=[0, [1, 2], 3]>
a.arr_object_id
#=> ...700
a.arr[1].object_id
#=> ...720
a.arr[1][1].object_id
#=> 5
2.object_id
#=> 5
b = ListArray.new(a.arr.dup)
#=> #<ListArray:0x0000574d96119258 @arr=[0, [1, 2], 3]>
b.arr
#=> [0, [1, 2], 3]
b.arr_object_id
#=> ...160 (different than a.arr_object_id)
b.arr[1].object_id
#=> ...720 (same as a.arr[1].object_id)
b.arr[1][1].object_id
#=> 5
Теперь измените значение a.arr[1][1]
:
a.arr[1][1] = 9
a.arr
#=> [0, [1, 9], 3] (as expected)
a.arr[1].object_id
#=> ...720 (no change)
b.arr
#=> [0, [1, 9], 3]
b.arr[1].object_id
#=> ...720 (no change)
Вы видите это изменение b[1][1]
также.Это потому, что содержимое объекта, которое является значением a.arr[1]
и b.arr[1]
, было изменено.Теперь попробуйте это.
a.arr[1] = [8, 0]
a.arr
#=> [0, [8, 0], 3] (as expected)
a.arr[1].object_id
#=> ...880 (a new object!)
b.arr
#=> [0, [1, 9], 3] (unchanged!)
b.arr[1].object_id
#=> ...720 (unchanged)
Для этого примера нам нужно написать:
a = ListArray.new [0, [1, 2], 3]
b = ListArray.new(a.arr.dup.map { |e| e.dup })
a.arr[1][1] = 9
a.arr
#=> [0, [1, 9], 3]
b.arr
#=> [0, [1, 2], 3] (no change!)
a.arr.dup.map { |e| e.dup }
упоминается как более глубокая копия из a.arr
чем a.arr.dup
.Если бы еще были более глубокие вложенные массивы ([1, [2, [3, 4]], 5]
), нам пришлось бы dup
, чтобы снизить уровни a.arr
.Для новичка из Ruby не важно полностью понимать, как создаются глубокие копии , просто они необходимы для достижения независимости дублированных копий объектов.