2016-06-04 5 views
0

내가 가지고 (아직 존재하지 않는 경우) 한 곳에서 새로운 Room 인스턴스를 생성하기로했다루비 배열

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

다음 코드가 아닌 전체 열에서 한 번에 . 해당 인스턴스를 [1][1]에 만들지 말고 [0][2], [1][2][2][2]으로 설정합니다.

왜 그렇습니까? 올바르게 작동하도록 변경하려면 어떻게합니까? 나는거야 (이전에 어떻게됩니까

@rooms = Array.new(3) { Array.new(3) } 

이 인수 Array.new(3) 평가 및 3 개 요소의 새로운 배열을 생성됩니다 있다는 것입니다 :

답변

7

나는, 당신이에이 줄 @rooms = Array.new(3, Array.new(3))을 변경해야 최근이에 고투 a). 그런 다음 Array.new(3, a)을 수행하면 모든 요소에 a이 포함 된 3 개의 요소로 이루어진 새 배열이 만들어집니다.

a은 변경 가능한 개체이므로 한 열에 대해 수정하면 모든 열이 수정됩니다.

솔루션에서 블록 { Array.new(3) }은 각 요소에 대해 평가되므로 각 열은 다른 배열입니다.

+0

글쎄, 그건 내가 창문을 통해 내 키보드를 던지게했을 것이다. 고맙습니다! – blob

+0

나는 그 감정을 안다. 문제 없다. –

+1

여기서 명확히하기 위해 "변경 가능한 개체"가되는 것이 정확히 문제가 아닙니다. 동일한 객체 참조가 모든 배열 슬롯에 저장됩니다. 'Array.new (3, Array.new) .map (& : object_id)'와'Array.new (3) {Array.new} .map (& : object_id)'의 차이점을 살펴보십시오. – tadman