我有以下代码
class Room
attr_reader :content, :descr
def initialize
@content = get_content
@descr = get_description
end
def get_content
['errors', 'bugs', 'syntax problems'].sample
end
def get_description
"This room has #{self.content}"
end
end
@rooms = Array.new(3, Array.new(3))
@rooms[1][1] ||= Room.new
# => #<Room:0x68985d8 @content="errors", @descr="This room has errors">
p @rooms # =>
#[[nil, #<Room:0x68985d8 @content="errors", @descr="This room has errors">, nil],
# [nil, #<Room:0x68985d8 @content="errors", @descr="This room has errors">, nil],
# [nil, #<Room:0x68985d8 @content="errors", @descr="This room has errors">, nil]]
@rooms = Array.new(3, Array.new(3))
@rooms[1][2] ||= Room.new
# => #<Room:0x6aaab58 @content="bugs", @description="This room contains bugs">
p @rooms # =>
#[[nil, nil, #<Room:0x6aaab58 @content="bugs", @descr="This room has bugs">],
# [nil, nil, #<Room:0x6aaab58 @content="bugs", @descr="This room has bugs">],
# [nil, nil, #<Room:0x6aaab58 @content="bugs", @descr="This room has bugs">]]
它应该在一个地方创建一个新的Room
实例(如果它还没有存在),而不是一次在整个列中。它不是在[1][1]
或其他任何地方创建所述实例,而是为[0][2]
,[1][2]
和[2][2]
设置。
为什么会这样?如何更改它才能正常工作?
答案 0 :(得分:7)
我最近在这方面遇到了困难,你必须将此行@rooms = Array.new(3, Array.new(3))
更改为:
@rooms = Array.new(3) { Array.new(3) }
前者发生的是参数Array.new(3)
被评估并创建一个包含3个元素的新数组(我称之为a
)。然后,执行Array.new(3, a)
创建一个包含3个元素的新数组,所有元素都包含a
。
a
是一个可变对象,因此当您为一列修改它时,所有列都会被修改。
在解决方案中,对每个元素评估块{ Array.new(3) }
,这就是为什么每列都是不同的数组。