Что такое хороший способ доступа к экземплярам? - PullRequest
0 голосов
/ 18 января 2019

Как мне написать свой класс для доступа к массиву для различных объектов?

class ListArray
  attr_accessor :arr

  def initialize arr
    @arr = arr
  end
end

a = ListArray.new([0, 1, 2, 3])
b = ListArray.new(a.arr)
a.arr[2] = 999
b.arr[2] = 4
a.arr[2] #=> 4  ?
b.arr[2] #=> 4

Когда я изменил значение b.arr[2] на 4, значение a.arr[2] (которое должно быть 999) принимает значение 4.

Я не знаю, что я сделал не так.

[править]

Мой полный код выглядит примерно так:

class OtherClass
   def list
end

class ListArray
   attr_accessor :arr
   def initialize arr
      @arr = arr
   end
   def putItem ...
   def getItem ...
   def cutList &bloc ...
end

a = ListArray.new obj1_other_class.list
  # obj2_other_class.list =>  [[1, 2], [3, 4], ... ]
  # [3, 4] is an item
b = ListArray.new obj2_other_class.list
a.putItem [5, 6]
c = ListArray.new a.arr
c.arr += b.arr
c.arr[1][0] = 7
      ...

Как мне избежать проблем с идентификатором объекта?

Ответы [ 2 ]

0 голосов
/ 18 января 2019
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 не важно полностью понимать, как создаются глубокие копии , просто они необходимы для достижения независимости дублированных копий объектов.

0 голосов
/ 18 января 2019

К

b = ListArray.new a.arr

Вы фактически передаете ссылку a.arr на b, а не на ее значение.

Вы можете сделать это так:

b = ListArray.new a.arr.dup

Проверьте этот вопрос , который касается передачи аргумента ссылки или значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...