如何从另一个内部 class 正确访问一个内部 class 中的实例变量?

How to properly access instance variables in one inner-class from another inner-class?

我正在制作一款井字游戏。我是 ruby 的新手,定义了一个 class Game,有两个内部 classes PlayerGameBoard。在 Game 中,我定义了两个实例变量 player1player2。我正在尝试访问方法 GameBoard.update_gameboard 中的 player1player2,就像这样

def update_gameboard(player)
      move = if player == 1
               @player1.moves[@player1.turn]
             else
               @player2.moves[@player2.turn]
             end
.
.
.

我收到错误:

/Users/Jacob/Development/RubyDev/RubymineProjects/TicTacToe/tictactoe.rb:85:in `update_gameboard': undefined method `moves' for nil:NilClass (NoMethodError)
    from /Users/Jacob/Development/RubyDev/RubymineProjects/TicTacToe/tictactoe.rb:44:in `play'
    from /Users/Jacob/Development/RubyDev/RubymineProjects/TicTacTOe/main.rb:30:in `<top (required)>'
    from -e:1:in `load'
    from -e:1:in `<main>'

Process finished with exit code 1

moves 不是一个方法,它是一个数组。 (playGame 中调用 update_gameboard 的方法)

如何从内部class(例如GameBoard)?

class Game
  attr_accessor :winner, :player1, :player2, :gameboard

  def initialize(player1_name, player2_name)
    @player1 = Player.new(player1_name, 'X')
    @player2 = Player.new(player2_name, 'O')
    @gameboard = GameBoard.new
  end
.
.
.
  class GameBoard
    attr_accessor :current_gameboard
    attr_reader :gameboard_move_map

    def initialize
          # initialize irrelevant GameBoard variables
    end

    def update_gameboard(player)
      move = if player == 1
               @player1.moves[@player1.turn]
             else
               @player2.moves[@player2.turn]
             end
      #then some more stuff that uses @player1 and @player2
    end
.
.
.
  end
end



这里的概念非常重要。 "Inner class" 并没有按照您的想法行事。除了命名空间之外,这两个 classes 之间绝对没有任何关系或特殊行为。基本上,只需将内部 class 视为完全单独定义的,因为这就是它的行为方式。

不过,您可以做的一件事是向 GameBoard 构造函数传递对 Game 实例的引用,这样您就可以访问实例变量:

(请注意,我只展示了与答案相关的部分,为了简洁起见,我省略了代码的其他部分):

class GameBoard
  attr_reader :game
  def initialize(game)
    @game = game
  end
end

class Game
  def initialize(player1_name, player2_name)
    @player1 = Player.new(player1_name, 'X')
    @player2 = Player.new(player2_name, 'O')

    # Note I pass the Game instance as self here:
    @gameboard = GameBoard.new(self)
  end
end

然后在 GameBoard 实例方法中,你可以这样做:

game.player1.moves[game.player1.turn]

game这里是attr_reader生成的方法(指initialize中设置的@game实例变量)