Ruby> Как использовать метод из одного класса в методе из другого класса? - PullRequest
1 голос
/ 29 января 2011

Я новичок в программировании, но хочу учиться, поэтому прошу прощения за этот вопрос.Я создал эту игру, чтобы помочь мне изучить ООП, и у меня возникли проблемы с ее частью.Вот что вызывает у меня проблемы:

У меня есть два класса.В строке 3 класса Player у меня есть некоторый код, который, вероятно, неверен, но в основном я пытаюсь использовать броню, чтобы изменить, сколько урона получает игрок.Я получаю сообщение об ошибке: "неопределенный метод 'protection' для nil: NilClass (NoMethodError)

У меня Armor в качестве другого класса. Я думаю, что проблема может быть связана с тем, что я вызываю @armor.protection, когда защита упоминается в Armor, а @armor упоминается в Player, но я не уверен, как это исправить. Я добавил весь код, который, по моему мнению, относится к моему вопросу ниже. Как я уже сказал, я действительно новичок вэто, поэтому, пожалуйста, используйте терминологию, понятную нубу.

class Player
  def equip(armor)
    @armor = armor
  end

  def hit(damage)
    #damage = damage - @armor.protection
    @health -= damage
  end
end  

class Armor
  def initialize(name, protection)
    @protection = protection
  end
end

РЕДАКТИРОВАТЬ: добавлен дополнительный код, чтобы показать все, что я собираюсь сделать для разъяснения.все, что у меня есть , хотя.: S Это, вероятно, страшно и зарычало.: P

class Player 

  def initialize(name, health) 
    @name = name 
    @health = health 
  end 

  def equip(armor) 
    @armor = armor 
  end 

  def health 
    @health 
  end 

  def health=(value) 
    @health = value 
  end 

  def hit(damage) 
damage = damage - @armor.protection 
    @health -= damage 
  end 

  def dead? 
if @health <= 0 
return true 
elsif @health > 0 
return false 
end 
  end 

  def name 
    @name 
  end 

  def attack(target) 
    damage = rand(30) 
    puts "#{@name} attacks #{target.name}" 
target.hit(damage) 
puts "#{@name} hits #{target.name} for #{damage} damage." 
  end 
end 

class Armor 
  def initialize(name, protection) 
  @protection = protection 
  end 
end 


player1 = Player.new("Melanie", 100) 
player2 = Player.new("a Monster", 200) 
shirt = Armor.new('shirt', 4) 
player1.equip(shirt) 

while player1.dead? == false && player2.dead? == false 
  player1.attack(player2) 
    if player2.health > 0 
      puts "#{player2.name}'s health is at #{player2.health}." 
    elsif player2.health <= 0 
puts "#{player2.name} has no health." 
end 
  player2.attack(player1) 
    if player1.health > 0 
      puts "#{player1.name}'s health is at #{player1.health}." 
    elsif player1.health <= 0 
puts "#{player1.name} has no health." 
end 
end 

if player1.health > player2.health 
  puts "#{player2.name} is dead." 
  puts "#{player1.name} wins." 
elsif player2.health > player1.health 
  puts "#{player1.name} is dead." 
  puts "#{player2.name} wins." 
elsif player2.health == player1.health 
  puts "#{player1.name} and #{player2.name} killed each other." 
end 

Ответы [ 4 ]

3 голосов
/ 29 января 2011

Если у вашего класса Armor есть метод protection, он будет работать нормально. Однако этого не происходит, поэтому даже если бы вы вызывали его из класса Armor, вы получите ту же ошибку. Чтобы определить его, вы можете использовать attr_reader или attr_accessor или определить его вручную.

class Armor
  attr_accessor :protection

  def initialize(name, protection)
    @protection = protection
  end
end

или

class Armor
  def initialize(name, protection)
    @protection = protection
  end

  def protection
    @protection
  end
end
2 голосов
/ 29 января 2011

Я только что выполнил ваш 2-й (полный) пример.

Помимо проблемы доступа, описанной в других ответах (просто добавьте attr_reader :protection к классу Armor), вы что-то упустили в тестовом сценарии :)

Сообщение об ошибке дает подсказку: undefined method 'protection' for nil:NilClass (NoMethodError).Учитывая, что это вызвано в 1-й строке метода hit, это означает, что @armor было nil, и, конечно, nil не является экземпляром Armor, поэтому у него нет метода protection.Почему это было ноль?Ну, посмотри, как начинается твой бой:

player1 = Player.new("Melanie", 100) 
player2 = Player.new("a Monster", 200) 
shirt = Armor.new('shirt', 4)
player1.equip(shirt) 

Только у Мелани есть рубашка, а ты вообще не дал доспеху монстра!Это не очень справедливо:)

Чтобы это исправить, вам нужно либо дать ему немного доспехов, либо изменить свой метод hit, чтобы он все еще работал, когда @armor не был инициализирован.Хороший ОО способ сделать это состоит в том, чтобы инициализировать всех игроков с фиктивной броней по умолчанию, которая не обеспечивает защиту:

class Player
  def initialize(name, health)
    @armor = Armor.new('nothing', 0)
    # ...

Готово!


Теперь,поскольку эта фиктивная броня будет полезна, какими бы ни были конкретные правила вашей игры, я бы абстрагировал ее с точки зрения класса Player, сделав вместо этого класс Armor ответственным за ее создание:

class Armor
  class << self # define a class method, like new
    def none
      self.new('nothing', 0)
    end
  end
  # ...

Тогда вы можете просто сказать Armor.none вместо Armor.new('nothing', 0) в Player.initialize.Таким образом, если вам нужно изменить внутреннюю работу Armor, вы можете обновить фиктивную броню одновременно, не затрагивая другие классы.

1 голос
/ 29 января 2011

Проблема здесь в том, что у вас есть @protection переменная экземпляра, но нет "средства доступа", чтобы добраться до нее.Переменные экземпляра являются частными для экземпляра класса, которым они принадлежат, поэтому, если вы хотите представить их внешнему миру, для этого необходимо настроить средства доступа.В этом случае вам понадобится:

class Armor
  attr_reader :protection
  ...
end

Это позволит вам вызвать @armor.protection и вернуть значение переменной @protection вашего экземпляра брони.

1 голос
/ 29 января 2011

Попробуйте это:

player = Player.new 
armor = Armor.new('Mythril', 100)
player = player.equip(armor)  #Initialise the armor object inside Player.

player.hit(10)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...