【问题标题】:Copy a class so that the old class is not modified when I modify the new one in Ruby复制一个类,这样当我在 Ruby 中修改新类时,旧类不会被修改
【发布时间】:2015-09-30 17:59:59
【问题描述】:

我有一些ConnectFour 类并且我有一个方法:

def apply_move!(column_number, symbol, row_number = 0)
  # Some gravity logic
  @board[row_number][column_number] = symbol
end

这会修改类。

我尝试在它周围编写一个包装器,它返回一个板并且不更改原始板,以便可以使用函数编程技术。

我的尝试是:

def apply_move(column_number, symbol)
  dummy = ConnectFour.new(@board)
  dummy.apply_move!(column_number, symbol)
  dummy
end

但是麻烦的是修改dummy也会修改原来的类本身!我怎样才能只修改dummydummy

更多代码和上下文

您可能对以下内容感兴趣:

class CpuWinIfPossible < Player
  def decide_move(board)
    (0...6).find do |move|
      board.apply_move(move, self.symbol).is_won?(self.symbol)
    end || (0...6).to_a.sample
  end
end

这里我循环并执行apply_move 到我的棋盘,从我上面的定义可以看出,apply_move 不应该改变棋盘,但是棋盘在这段代码运行后显示 7 (+ 1) 个动作:它看起来像这样:

Player X: Where would you like to play (Number from 1 to 7) ? 
2




 O   O 
OXOOOO 
The winner is O

构造函数

class ConnectFour
  attr_accessor :board


  def initialize(board)
    @board = board
  end

【问题讨论】:

  • 我不明白你展示的任何方法如何可以改变类。一定有其他事情发生了,你没有向我们展示。另外,“老班”和“新班”是什么意思?我这里只能看到一节课,ConnectFour
  • @JörgWMittag 添加了一个重要的方法,可能我的术语并不准确,因为当我说类时,我的意思是包含类的特定实例的变量
  • 可以分享ConnectFour的构造方法吗?我很确定有问题,不要发送@board,而是发送@board.clone@board.dup
  • @Aguardientico 添加了,感谢您的努力,即使我的问题不完整:D

标签: ruby oop functional-programming


【解决方案1】:

我认为这与@board 的当前状态有关,如果您将ConnectFour#initialize 更改为如下所示,我认为它应该可以工作

def initialize(board)
  @board = board.dup
end

如果你使用的是 Rails,你可以使用deep_dup

def initialize(board)
  @board = board.deep_dup
end

【讨论】:

  • 非常感谢,所以问题是 @board 真的被所有 CONNectFour 实例共享?
  • 等一下,我想我还是有问题,无论如何我还是非常感谢你
  • 这只会复制@board 数组,而不是@board 数组中包含的数组。 真正的 问题是 Ruby 是一种面向对象的语言,而不是面向数组的整数数组语言,因此您应该真正为您的开发板使用 Board 对象,而不是一个整数数组。
  • @JörgWMittag 我知道问题比看起来更深,Ruby 缺乏支持是因为我不遵守 OO
  • 看起来rails有一个deep_dup方法apidock.com/rails/v4.0.2/Array/deep_dup更新答案
【解决方案2】:

解决我的问题的一个技巧是:

def initialize(board)
  @board = board.map(&:dup)
end

但正如@JörgWMittag 所说,我真的应该让我的代码更加面向对象,以适应 Ruby 风格,并且不再需要这种解决方法。

【讨论】:

  • @admdrew 我以第二人称自言自语,以使帖子对未来的访问者更具可读性
  • @admdrew 现在是第一人称。
【解决方案3】:

您可以制作该课程的深层副本:

new_class = Marshal.load(Marshal.dump(ConnectFour))

然后从那里开始(dummy = new_class.new(@board) 等)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-02
    • 1970-01-01
    • 2021-01-30
    • 2019-01-09
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多