Как правильно получить доступ к переменным экземпляра в одном внутреннем классе из другого внутреннего класса? - PullRequest
0 голосов
/ 13 января 2019

Я создаю игру в крестики-нолики. Я новичок в ruby ​​и определил класс Game с двумя внутренними классами Player и GameBoard. В Game я определяю две переменные экземпляра player1 и player2. Я пытаюсь получить доступ к player1 и player2 внутри метода GameBoard.update_gameboard, как это

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 это не метод, это массив. (play - это метод в Game, который вызывает update_gameboard)

Как получить доступ к переменным экземпляра внешнего класса (Game) из внутреннего класса (например, 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



1 Ответ

0 голосов
/ 13 января 2019

Действительно важная концепция здесь. «Внутренний класс» не делает то, что вы думаете. Между этими двумя классами нет абсолютно никакого отношения или особого поведения, кроме пространства имен. По сути, просто относитесь к внутреннему классу так, как будто он определен совершенно отдельно, потому что так он себя ведет.

Однако вы можете передать конструктору 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 (ссылающийся на переменную экземпляра @game, установленную в initialize).

...