#bowling.rb class Bowling @game_score = 0 def hit(pins) @game_score = @game_score + pins end def score @game_score end end
解决方法
#bowling.rb class Bowling @game_score = 0 # (1)
在这一点(1),我们仍然在班级保龄球.记住:类只是像其他任何对象.因此,在这一点上,您将0分配给类对象Bowling的实例变量@game_score.
def hit(pins) @game_score = @game_score + pins # (2)
现在(2),我们是保龄球课的一个实例方法.即:这是一种属于保龄球实例的方法.所以,现在实例变量@game_score属于Bowling类的一个实例,而不是类本身.
由于这个实例变量从来没有被初始化为任何东西,所以它将评估为nil(在Ruby中,未初始化的变量总是计算为nil),所以这个评估结果为@game_score = nil引脚,并且由于没有#方法,这将导致在引发的NoMethodError异常中.
end def score @game_score # (3)
在这里(3),我们再次进入保龄球课的一个实例方法.这将总是评估为零,原因如上:@game_score从未初始化,因此评估为nil.
end end
我们可以使用Ruby的反射功能来看看发生了什么:
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分为两个阶段的对象创建:内存分配和对象初始化,内存分配由一个名为alloc的类方法完成,对象初始化由一个称为initialize的实例方法(Objective-C程序员会认识到这一点).alloc是一个类方法的原因只是在执行的这一点上还没有实例,初始化的一个实例方法是对象初始化显然是每个对象,为了方便起见,有一个称为new的标准工厂类方法,它为您调用alloc和initialize.)
class Bowling def initialize @game_score = 0 end end
我们来测试一下:
c = Bowling.new p c.score # => 0 c.hit(2) p c.score # => 2
BTW:只是一些小的Ruby样式提示:缩进是2个空格,而不是1个选项卡.而你的命中方法将会更加惯用@game_score =引脚.