如何编写我的类以访问不同对象的数组?
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
...
如何避免对象的相同id问题?
答案 0 :(得分:4)
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
的值并获取其对象ID:
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
之所以如此,是因为a
和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]
的值对象的 contents 已被更改。现在尝试这个。
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新手来说,完全理解深层副本的构造并不重要,仅需要它们就可以实现对象的重复副本的独立性。
答案 1 :(得分:3)
通过
spring stop
您实际上将b = ListArray.new a.arr
的引用转移到b,而不是值。
您可以这样做:
a.arr
检查this question,这与引用或值的参数传递有关。