Ruby:从方法调用类实例时遇到麻烦

时间:2014-09-11 18:43:24

标签: ruby class instance-variables

我显然很擅长Ruby,而且编程一般,非常感谢任何帮助。

这是我的代码段:

class Player
    attr_accessor :name, :hp

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

    def name
        @name
    end

    def hp
        @hp
    end
end

def prompt
    print "> "
end

prompt; pname = gets.chomp
player = Player.new(pname, rand(20..30))

puts "#{player.name} \:\: #{player.hp} HP"

def test
    puts "#{player.name} \:\: #{player.hp} HP - IN METHOD"
end

test

运行时,结果如下:

$ ruby​​ wtf.rb

> Test Name

Test Name :: 20 HP

wtf.rb:24:in `test': undefined local variable or method `player' for main:Object (NameError) from wtf.rb:27:in `<main>'

为什么我的通话工作在第一个实例,而不是第二个?是因为它现在正在寻找一个新的&#34;播放器&#34; &#34;测试&#34;中的变量方法?如果是这样,我如何从之前创建的类实例中调用它?

谢谢!

3 个答案:

答案 0 :(得分:1)

player被定义为方法test范围之外的局部变量,

player的引用更改为@player,使其成为实例变量

以下是范围和变量的快速reference,以及similar question

作为旁注,您不应将test用作方法名称,因为它已在Kernel上定义

irb(main):001:0> method(:test)
=> #<Method: Object(Kernel)#test>

答案 1 :(得分:0)

def test
  puts "#{player.name} \:\: #{player.hp} HP - IN METHOD"
end

您忘记将player传递给方法:

def test(player)
  puts "#{player.name} \:\: #{player.hp} HP - IN METHOD"
end

test(player) # => player = Player.new(pname, rand(20..30)) :: 22 HP - IN METHOD

答案 2 :(得分:0)

Ruby没有像Javascript这样的函数的词法范围,所以这个(ruby):


player = Player.new(pname, rand(20..30))
def test
    # error: undefined variable or method 'player', 
    # this happens because player was defined
    # in an unrelated scope outside this method
    puts "#{player.name} \:\: #{player.hp} HP - IN METHOD"
end
test

NOT 等效于此(javascript)


var player = new Player(pname, ...);
var test = function() {
    # works as expected, player is available because it was defined
    # in the parent scope
    console.log(player.name + "\:\:" + player.hp + " HP - IN METHOD");
};
test();

如果你想在ruby上使用类似于词法范围的东西,也许你应该使用lambda


player = Player.new(pname, rand(20..30))
test = lambda do
    # works as expected, this block scope inherits from parent scope where the block
    # was created, so, it can access player local variable
    puts "#{player.name} \:\: #{player.hp} HP - IN METHOD"
end
test.call