Ruby 在另一个类的方法中使用一个类的方法?
我创建这个游戏是为了学习OOP,但我在部分方面遇到了问题。以下是给我带来问题的原因: 我有两节课。在类玩家的第3行,我有一些可能是错误的代码,但基本上,我想做的是使用护甲来修改玩家受到的伤害。不过,我得到了一个错误:nil:NilClass NoMethodError的未定义方法“protection” 我有盔甲作为另一个职业。我认为这个问题可能与我在《盔甲》中提到防护和《玩家》中提到@armor时,我会调用@armor.protection有关,但我不确定如何解决这个问题。我已经添加了我认为与我下面的问题相关的所有代码。就像我说的,我在这方面很新,所以请使用noob能理解的术语Ruby 在另一个类的方法中使用一个类的方法?,ruby,class,methods,Ruby,Class,Methods,我创建这个游戏是为了学习OOP,但我在部分方面遇到了问题。以下是给我带来问题的原因: 我有两节课。在类玩家的第3行,我有一些可能是错误的代码,但基本上,我想做的是使用护甲来修改玩家受到的伤害。不过,我得到了一个错误:nil:NilClass NoMethodError的未定义方法“protection” 我有盔甲作为另一个职业。我认为这个问题可能与我在《盔甲》中提到防护和《玩家》中提到@armor时,我会调用@armor.protection有关,但我不确定如何解决这个问题。我已经添加了我认为与
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
编辑:添加了额外的代码,以显示所有我正在进行的澄清。不过,我并不指望有人能看完我所有的资料它可能很吓人,而且乱七八糟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
试试这个:
player = Player.new
armor = Armor.new('Mythril', 100)
player = player.equip(armor) #Initialise the armor object inside Player.
player.hit(10)
试试这个:
player = Player.new
armor = Armor.new('Mythril', 100)
player = player.equip(armor) #Initialise the armor object inside Player.
player.hit(10)
如果你的护甲等级有一个防护方法,它会很好的工作。但是它不是,所以即使你从装甲类内部调用它,你也会得到同样的错误。要定义它,可以使用attr\u reader或attr\u accessor,也可以手动定义
class Armor
attr_accessor :protection
def initialize(name, protection)
@protection = protection
end
end
或
如果你的护甲等级有一个防护方法,它会很好的工作。但是它不是,所以即使你从装甲类内部调用它,你也会得到同样的错误。要定义它,可以使用attr\u reader或attr\u accessor,也可以手动定义
class Armor
attr_accessor :protection
def initialize(name, protection)
@protection = protection
end
end
或
这里的问题是您有一个@protection实例变量,但没有访问器。实例变量对于它们所属的类的实例是私有的,因此,如果要将它们公开给外部世界,必须设置访问器。在这种情况下,您需要:
class Armor
attr_reader :protection
...
end
这将允许您调用@armor.protection,并返回armor实例的@protection变量的值。这里的问题是您有一个@protection实例变量,但没有访问器。实例变量对于它们所属的类的实例是私有的,因此,如果要将它们公开给外部世界,必须设置访问器。在这种情况下,您需要:
class Armor
attr_reader :protection
...
end
这将允许您调用@armor.protection,并将返回您的装甲实例的@protection变量的值。我刚刚运行了您的第二个完整示例 除了在其他答案中解释的访问者问题之外,只需添加attr_reader:protection to class Armor,您在测试场景中忽略了一些东西: 错误消息给出提示:nil:NilClass NoMethodError的未定义方法“protection”。考虑到这是在命中方法的第1行中造成的,这意味着@armor是零,当然,零不是装甲的一个实例,因此它没有保护方法。为什么是零?好吧,看看你的战斗是如何开始的:
player1 = Player.new("Melanie", 100)
player2 = Player.new("a Monster", 200)
shirt = Armor.new('shirt', 4)
player1.equip(shirt)
只有梅勒妮有一件衬衫,而你却没有给怪物任何盔甲!不太公平,是不是:
要解决这个问题,你要么给他一些护甲,要么改变你的命中方法,使它在@armor未初始化时仍然有效。一个很好的OO方法是使用默认的虚拟盔甲初始化所有玩家,该盔甲不提供任何保护:
class Player
def initialize(name, health)
@armor = Armor.new('nothing', 0)
# ...
完成了
现在,由于无论游戏的具体规则是什么,虚拟盔甲都是有用的,我将从职业玩家的角度抽象它,让职业盔甲负责创建它:
class Armor
class << self # define a class method, like new
def none
self.new('nothing', 0)
end
end
# ...
然后你可以说Armor.none而不是Armor.new'nothing',Player.initialize中的0。这样,如果您需要更改装甲内部的工作方式,您可以同时更新虚拟装甲,而不必涉及其他类。我刚刚运行了您的第二个完整示例 除了在其他答案中解释的访问者问题之外,只需添加attr_reader:protection to class Armor,您在测试场景中忽略了一些东西: 错误消息给出提示:nil:NilClass NoMethodError的未定义方法“protection”。考虑到这是在命中方法的第1行中造成的,这意味着@armor是零,当然,零不是装甲的一个实例,因此它没有保护方法。为什么是零?好吧,看看你的战斗是如何开始的:
player1 = Player.new("Melanie", 100)
player2 = Player.new("a Monster", 200)
shirt = Armor.new('shirt', 4)
player1.equip(shirt)
只有梅勒妮有一件衬衫,而你却没有给怪物任何盔甲!不太公平,是不是:
要解决这个问题,你要么给他一些护甲,要么改变你的命中方法,使它在@armor未初始化时仍然有效。一个很好的OO方法是使用默认的虚拟盔甲初始化所有玩家,该盔甲不提供任何保护:
class Player
def initialize(name, health)
@armor = Armor.new('nothing', 0)
# ...
完成了
现在,由于无论游戏的具体规则是什么,虚拟盔甲都是有用的,我将从职业玩家的角度抽象它,让职业盔甲负责创建它:
class Armor
class << self # define a class method, like new
def none
self.new('nothing', 0)
end
end
# ...
然后你可以说armar.none代替armar.new'nothing',在Player.in中为0
初始化。这样,如果您需要更改盔甲的内部工作方式,您可以同时更新虚拟盔甲,而不必接触其他类。应该是player=player.new和player.equiparmbor和player.hit10,这些都是实例方法。我想我已经有类似的方法了。我已经添加了所有需要澄清的代码。希望它有意义。应该是player=player.new和player.equiparmbor和player.hit10,这些都是实例方法。我想我已经有了类似的东西。我已经添加了所有需要澄清的代码。希望这是有意义的。这确实帮助我理解了attr_阅读器,attr_访问器,因为我以前从未得到过它,但我认为我的部分问题是我没有将装甲与装甲绑定在一起。我不知道该怎么做。到目前为止,程序还不知道说盔甲,我的意思是,在这个球员的情况下,一件球衣。除了在damage=damage-@armor.protection中,我唯一提到的护甲是小写字母a,它与职业玩家装备的定义一致:这无疑帮助我理解了attr_阅读器,attr_访问器,因为我以前从未得到过它,但我认为我的部分问题是我没有将装甲与装甲绑定在一起。我不知道该怎么做。到目前为止,程序还不知道说盔甲,我的意思是,在这个球员的情况下,一件球衣。除了在damage=damage-@armor.protection中,我唯一提到的护甲是小写字母a,它与职业玩家装备的定义一致:现在的SAs,程序不知道说盔甲,我的意思是,在这个球员的情况下,一件衬衫。除了在damage=damage-@armar.protection中,我唯一提到的护甲是小写字母a,它的定义是在类玩家中装备。我尝试了第二个例子,希望它能解决这个问题,但无论哪种情况,我仍然有相同的错误。我知道我有点不知所措,但我确实了解很多,这绝对是一次学习经历S@Melanie:首先,我的代码是错误的,因为当我提到保护时,我无意中键入了armor,所以它无法工作。现在我修复了它,只要你在调用任何使用@armor的方法之前调用Equipm,它就会工作。要求首先调用Equipm的一个更好的解决方案可能是在玩家类初始化方法中将@armor初始化为零的armor类实例。这样一来,如果玩家一开始没有盔甲,你就不必担心了。仅供参考和谷歌素材:@Mike Bethany的建议是空对象重构。到目前为止,程序不知道说盔甲,我的意思是,在这个玩家的情况下,一件衬衫。除了在damage=damage-@armar.protection中,我唯一提到的护甲是小写字母a,它的定义是在类玩家中装备。我尝试了第二个例子,希望它能解决这个问题,但无论哪种情况,我仍然有相同的错误。我知道我有点不知所措,但我确实了解很多,这绝对是一次学习经历S@Melanie:首先,我的代码是错误的,因为当我提到保护时,我无意中键入了armor,所以它无法工作。现在我修复了它,只要你在调用任何使用@armor的方法之前调用Equipm,它就会工作。要求首先调用Equipm的一个更好的解决方案可能是在玩家类初始化方法中将@armor初始化为零的armor类实例。这样一来,如果玩家一开始没有盔甲,你就不用担心了。仅供参考和谷歌素材:@Mike Bethany的建议是空对象重构。哇!太棒了!非常感谢你!我不会认为这是百万年来的问题。我必须学会更好地阅读错误消息。至少我比老天爷高了几步!一个错误!不客气。顺便说一句,如果我能挑出更多的细节,我会在玩家1死的时候看到它false&&player2.dead?==错误的笨拙的风格!至少,用非某个布尔值替换某个布尔值==false;就我个人而言,我会代替死者?由一个活的谓词进行谓词?一个你可以直接使用而不用否定的词:是的,我朋友就是这么说的!非常感谢。哇!太棒了!非常感谢你!我不会认为这是百万年来的问题。我必须学会更好地阅读错误消息。至少我比老天爷高了几步!一个错误!不客气。顺便说一句,如果我能挑出更多的细节,我会在玩家1死的时候看到它false&&player2.dead?==错误的笨拙的风格!至少,用非某个布尔值替换某个布尔值==false;就我个人而言,我会代替死者?由一个活的谓词进行谓词?一个你可以直接使用而不用否定的词:是的,我朋友就是这么说的!非常感谢。