在Ruby中,为什么在启动irb之后,foo.nil?说未定义的错误,@ foo.nil?给出"真实"和@@ wah.nil?再次出错?

nop*_*ole 13 ruby instance-variables local-variables class-variables

在Ruby 1.8.7和1.9.2中也是如此:

$ irb

ruby-1.8.7-p302 > foo.nil?
NameError: undefined local variable or method `foo' for #<Object:0x3794c>
    from (irb):1

ruby-1.8.7-p302 > @bar.nil?
 => true 

ruby-1.8.7-p302 > @@wah.nil?
NameError: uninitialized class variable @@wah in Object
    from (irb):3
Run Code Online (Sandbox Code Playgroud)

为什么实例变量的处理方式与本地和类变量不同?

Jör*_*tag 17

在Ruby中,大多数未初始化或甚至不存在的变量都会进行评估nil.对于局部变量,实例变量和全局变量都是如此:

defined? foo       #=> nil
local_variables    #=> []
if false
  foo = 42
end
defined? foo       #=> 'local-variable'
local_variables    #=> [:foo]
foo                #=> nil
foo.nil?           #=> true

defined? @bar      #=> nil
instance_variables #=> []
@bar               #=> nil
@bar.nil?          #=> true
# warning: instance variable @bar not initialized

defined? $baz      #=> nil
$baz               #=> nil
# warning: global variable `$baz' not initialized
$baz.nil?          #=> true
# warning: global variable `$baz' not initialized
Run Code Online (Sandbox Code Playgroud)

但是,类层次结构变量和常量不是这样的:

defined? @@wah     #=> nil
@@wah
# NameError: uninitialized class variable @@wah in Object

defined? QUUX      #=> nil
QUUX
# NameError: uninitialized constant Object::QUUX
Run Code Online (Sandbox Code Playgroud)

这是一个红鲱鱼:

defined? fnord     #=> nil
local_variables    #=> []
fnord
# NameError: undefined local variable or method `fnord' for main:Object
Run Code Online (Sandbox Code Playgroud)

你在这里得到错误的原因不是单位化的局部变量没有评估nil,它是fnord不明确的:它可以是一个无参数的消息发送到默认的接收器(即相当于self.fnord())访问局部变量fnord.

为了消除歧义,你需要添加一个接收器或参数列表(即使是空的)来告诉Ruby它是一个消息发送:

self.fnord
# NoMethodError: undefined method `fnord' for main:Object
fnord()
# NoMethodError: undefined method `fnord' for main:Object
Run Code Online (Sandbox Code Playgroud)

或者确保解析器(而不是求值程序)在使用之前解析(执行)赋值,告诉Ruby它是一个局部变量:

if false
  fnord = 42
end
fnord              #=> nil
Run Code Online (Sandbox Code Playgroud)

为什么实例变量的处理方式与本地和类变量不同?

实际上并非如此.它被视为局部变量.类层次结构变量是行为不同的变量,局部变量,实例变量和全局变量的行为都相同.

还有其他原因......类变量的行为也不能吗?

我不知道.例如变量非常方便,因为与Java不同,例如,实例变量在类定义中声明,因此对于类的每个实例始终存在,在Ruby中,实例变量不会在任何地方声明.一旦他们被分配,他们就会神奇地生存.由于实例变量不一定能保证存在,因此编写使用实例变量的方法如果抛出异常就会很痛苦.

为什么类层次结构变量不同,我不知道.也许这是因为无论如何都没有人使用它们,或者因为它们通常倾向于在类体中初始化,并且在未初始化时根本不被访问.