尽管克隆了共享的数组

时间:2014-03-13 18:46:42

标签: ruby arrays clone

我有一个这样的课程:

class Tiles
  attr_accessor :board
  def initialize
    @board = Array.new(4) { Array.new(4) { 0 } }
  end
  ...

后来,我称这种方法为:

def display_board
  padded_board = @board.clone
  padded_board.each_with_index do |row, x|
    row.each_with_index do |item, y|
      padded_board[x][y] = pad_number(item)
    end
    puts row.join ' '
  end
end  

我随时更改padded_board@board也会发生变化。我无法弄清楚为什么会这样。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

这是因为当您clone时,您正在创建数组@board的新实例,但其元素(也是数组)不会被新实例替换。你没有深入克隆最终元素。你需要做深度克隆。您可能希望查看一些答案和建议的宝石herehere

答案 1 :(得分:0)

原因是数组实际上是一组指向其他对象的指针,在这种情况下,这些对象是另一个数组。在克隆数组时,您正在创建指向相同对象的新指针。通过调用padded_board[x][y]=,您正在修改padded_board[x]数组,该数组由@boardpadded_board引用。

要修复它,您不仅需要复制数组,还需要复制此数组的每个元素。在他的情况下,这应该足够了:

   padded_board = @board.map(&:clone)

在更一般的情况下,使用deep_dup方法扩展Array非常有用。 Rails在ActiveSupport模块中定义了这种方法,通过添加`require' active_support / core_ext / object / deep_dup'也可以在任何非rails项目中使用。