新手总数:红宝石中的实例变量? [英] Total newbie: Instance variables in ruby?

查看:79
本文介绍了新手总数:红宝石中的实例变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Pardon the total newbiew question but why is @game_score always nil?

#bowling.rb

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

    def score
        @game_score
    end
end

推荐答案

让我们遍历代码,好吗?

Let's walk through the code, shall we?

#bowling.rb

class Bowling
  @game_score = 0 # (1)

在这一点上(1),我们仍然在 class Bowling之内.请记住:类就是与其他对象一样的对象.因此,此时,您要将0分配给类对象Bowling 的实例变量@game_score .

At this point (1), we are still inside the class Bowling. Remember: classes are just objects like any other. So, at this point you are assigning 0 to the instance variable @game_score of the class object Bowling.

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

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

Now (2), we are inside an instance method of the Bowling class. I.e.: this is a method that is going to belong to an instance of Bowling. So, now the instance variable @game_score belongs to an instance of the Bowling class, and not to the class itself.

由于实例变量从未初始化为任何内容,因此它将求值为nil(在Ruby中,未初始化的变量始终为nil),因此其求值为@game_score = nil + pins,并且nil没有#+方法,这将导致引发NoMethodError异常.

Since this instance variable is never initialized to anything, it will evaluate to nil (in Ruby, uninitialized variables always evaluate to nil), so this evaluates to @game_score = nil + pins and since nil doesn't have a #+ method, this will result in a NoMethodError exception being raised.

 end
 def score
  @game_score # (3)

在这里(3),我们再次位于Bowling类的 instance方法中.由于我上面概述的原因,它始终会评估为nil:@game_score从未初始化,因此它的评估结果为nil.

And here (3), we are again inside an instance method of the Bowling class. This will always evaluate to nil, for the reason I outlined above: @game_score is never initialized, therefore it evaluates to nil.

 end
end

我们可以使用Ruby的反射功能来查看发生了什么:

We can use Ruby's reflection capabilities to take a look at what's going on:

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

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

Now let's inject a value into the instance variable:

b.instance_variable_set(:@game_score, 1)
p b.score # => 1
b.hit(3)
p b.score # => 4

因此,我们看到一切正常,我们只需要弄清楚如何确保实例变量被初始化即可.

So, we see that everything works as it should, we only need to figure out how to make sure the instance variable gets initialized.

为此,我们需要编写一个初始化方法.奇怪的是,初始化器方法实际上是称为initialize的私有 instance方法. (为什么initialize是实例方法而不是类方法的原因实际上很简单.Ruby将对象创建分为两个阶段:内存分配和对象初始化.内存分配由 class 完成. alloc方法和对象初始化由称为initialize instance 方法完成(Objective-C程序员会认识到这一点).alloc是类方法的原因很简单:此时执行尚无实例,而initialize是实例方法的原因是对象初始化显然是针对每个对象的;为方便起见,有一个称为new的标准工厂类方法,它同时调用了这两种方法. allocinitialize).

To do that, we need to write an initializer method. Strangely, the initializer method is actually a private instance method called initialize. (The reason why initialize is an instance method and not a class method, is actually quite simple. Ruby splits object creation in two phases: memory allocation and object initialization. Memory allocation is done by a class method called alloc and object initialization is done by an instance method called initialize. (Objective-C programmers will recognize this.) The reason why alloc is a class method is simply that at this point in the execution there is no instance yet. And the reason that initialize is an instance method is that object initialization is obviously per-object. As a convenience, there is a standard factory class method called new that calls both alloc and initialize for you.)

class Bowling
 def initialize
  @game_score = 0
 end
end

让我们对此进行测试:

c = Bowling.new
p c.score # => 0
c.hit(2)
p c.score # => 2

顺便说一句:Ruby的一些小技巧:缩进是2个空格,而不是1个制表符.而您的hit方法更习惯于使用@game_score += pins.

BTW: just some minor Ruby style tips: indentation is 2 spaces, not 1 tab. And your hit method would more idiomatically be @game_score += pins.

这篇关于新手总数:红宝石中的实例变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆