总新手:ruby中的实例变量?

时间:2009-10-10 18:12:30

标签: ruby instance-variables

原谅新的总问题,但为什么@game_score总是为零呢?

#bowling.rb

class Bowling
  @game_score = 0
    def hit(pins)
        @game_score = @game_score + pins
    end

    def score
        @game_score
    end
end

4 个答案:

答案 0 :(得分:37)

让我们一起来看看代码吧?

#bowling.rb

class Bowling
  @game_score = 0 # (1)

此时(1),我们仍然在 Bowling内。请记住:类只是与其他类似的对象。因此,此时您要将0分配给类对象@game_score 的实例变量Bowling

 def hit(pins)
  @game_score = @game_score + pins # (2)

现在(2),我们在Bowling类的实例方法中。即:这是一种属于Bowling实例的方法。所以,现在实例变量@game_score属于Bowling类的实例,而不属于类本身。

由于实例变量从未初始化为任何内容,因此它将计算为nil(在Ruby中,未初始化的变量始终求值为nil),因此计算结果为{ {1}}由于@game_score = nil + pins没有nil方法,因此会导致#+异常。

NoMethodError

在这里(3),我们再次进入 end def score @game_score # (3) 类的实例方法。这总是评估为Bowling,原因如上所述:nil永远不会被初始化,因此评估为@game_score

nil

我们可以使用Ruby的反射功能来了解正在发生的事情:

 end
end

现在让我们在实例变量中注入一个值:

p Bowling.instance_variable_get(:@game_score) # => 0
b = Bowling.new
p b.instance_variable_get(:@game_score) # => nil

因此,我们看到一切都按预期工作,我们只需要弄清楚如何确保实例变量初始化。

为此,我们需要编写初始化方法。奇怪的是,初始化方法实际上是一个名为b.instance_variable_set(:@game_score, 1) p b.score # => 1 b.hit(3) p b.score # => 4 的私有实例方法。 (initialize是实例方法而不是类方法的原因实际上非常简单.Ruby分为两个阶段创建对象:内存分配和对象初始化。内存分配由类完成方法名为initialize,对象初始化由名为alloc实例方法完成。(Objective-C程序员会认识到这一点。)initialize的原因类方法很简单,在执行的这一点上还没有实例。alloc是一个实例方法的原因是对象初始化显然是每个对象。为方便起见,有一个标准名为initialize的工厂类方法,为您调用newalloc。)

initialize

让我们测试一下:

class Bowling
 def initialize
  @game_score = 0
 end
end

BTW:只是一些小的Ruby风格提示:缩进是2个空格,而不是1个标签。而您的c = Bowling.new p c.score # => 0 c.hit(2) p c.score # => 2 方法更具惯用性hit

答案 1 :(得分:16)

因为你没有

def initialize
  @game_score = 0
end

类定义中的赋值没有按照您的想法执行,并且在调用hit时,它无法添加到nil

如果你现在问 @game_score发生了什么?,那么,永远记住 Class是一个对象 Object是一个类

Ruby类具有类似Zen的“真实”存在的方式很酷。 Ruby并不精确地具有命名类,而是类名是对类Class的对象的引用。通过在实例方法之外分配@game_score,您创建了一个类实例变量,这是类对象Bowling的一个属性,它是类Class的一个实例。通常,这些对象非常有用。 (参见第1章, The Ruby Way ,Hal Fulton。)

答案 2 :(得分:9)

定义

@game_score称为类实例变量,它是为单例类对象定义的变量:

class << Bowling
  attr_accessor :game_score
end

Bowling.game_score #=> 0

这可以说明与为实例对象定义的普通实例变量不同。

答案 3 :(得分:0)

@game_score永远不会在这里获得零值 - 你需要把它放在初始化中,如

def初始化   @game_score = 0 端