You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby面向对象编程:更新Game类中Player实例变量的正确方式

关于Ruby Tic-tac-toe游戏中Player实例更新的问题解答

为什么不需要重新赋值game.player_1 = p1?

Ruby中对象采用引用传递机制:当你在Game的初始化方法里把p1、p2赋值给@player_1、@player_2时,这两个实例变量本质上是指向同一个Player对象的引用。也就是说,game.player_1和你创建的p1变量,指向的是内存中同一个Player实例。

所以当你调用p1.play方法修改自身的selection数组时,game.player_1指向的对象状态已经同步更新,自然能获取到最新的selection,完全不需要重新赋值。

正确的更新方式分两种场景

1. 修改现有Player对象的内部状态(你的当前场景)

这是最符合OOP封装原则的方式:让Player类自己负责管理自身状态,通过类内部的方法(比如你的play方法)来修改属性,Game类不需要做任何重新赋值操作。

示例代码:

class Player
  attr_reader :selection, :name, :marker

  def initialize(name, marker)
    @name = name
    @marker = marker
    @selection = []
  end

  # 让Player自己处理落子逻辑,同时调用Game的方法更新游戏状态
  def play(game, position)
    @selection << position
    game.record_move(position, @marker)
  end
end

class Game
  attr_reader :player_1, :player_2
  attr_reader :board

  def initialize(p1, p2)
    @player_1 = p1
    @player_2 = p2
    @board = Array.new(9, nil) # 用board代替numbers,语义更清晰
  end

  # Game自己负责维护棋盘状态,对外提供公共方法
  def record_move(position, marker)
    @board[position] = marker unless @board[position]
  end
end

# 使用示例
alice = Player.new("Alice", "X")
bob = Player.new("Bob", "O")
game = Game.new(alice, bob)

alice.play(game, 0)
puts game.player_1.selection # 输出 [0],无需重新赋值
puts game.board[0] # 输出 "X"

2. 替换Game中的Player对象(场景:比如中途更换玩家)

如果你的需求是把game.player_1换成一个全新的Player实例(不是修改现有对象的状态),那才需要给Game类提供赋值的入口。可以通过attr_writer或者自定义setter方法实现:

示例代码:

class Game
  attr_reader :player_1, :player_2
  attr_writer :player_1, :player_2 # 提供写权限
  # 或者用attr_accessor同时提供读写权限
  # ...其他代码
end

# 替换player_1为新玩家
charlie = Player.new("Charlie", "X")
game.player_1 = charlie

额外的封装建议

  • 避免让Player直接修改Game的内部变量(比如直接操作game.numbers),最好通过Game提供的公共方法来更新游戏状态,这样职责划分更清晰,也方便后续扩展和维护。
  • 不要给Player的selection设置外部可写权限(比如避免用attr_accessor),只保留attr_reader,让状态修改完全由Player内部方法控制,保证数据的安全性。

内容的提问来源于stack exchange,提问作者Ong K.S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 08:22:14