在Ruby中,为什么在启动irb之后,foo.nil?表示未定义的错误,并且@foo.nil?给予;“真的”;,和@wah.nil?又犯错误了?

在Ruby中,为什么在启动irb之后,foo.nil?表示未定义的错误,并且@foo.nil?给予;“真的”;,和@wah.nil?又犯错误了?,ruby,instance-variables,local-variables,class-variables,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: uninit

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
$irb
ruby-1.8.7-p302>foo.nil?
NameError:未定义的局部变量或方法“foo”#
来自(irb):1
ruby-1.8.7-p302>@bar.nil?
=>正确
ruby-1.8.7-p302>@wah.nil?
NameError:对象中未初始化的类变量@@wah
来自(irb):3

为什么实例变量的处理方式不同于局部变量和类变量?

在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
但是,对于类层次结构变量和常量,情况并非如此:

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

defined? QUUX      #=> nil
QUUX
# NameError: uninitialized constant Object::QUUX
这是一条红鲱鱼:

defined? fnord     #=> nil
local_variables    #=> []
fnord
# NameError: undefined local variable or method `fnord' for main:Object
这里出现错误的原因不是单位化局部变量的计算结果不为
nil
,而是
fnord
不明确:它可能是发送给默认接收器的无参数消息(即相当于
self.fnord()
),也可能是对局部变量
fnord
的访问

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

self.fnord
# NoMethodError: undefined method `fnord' for main:Object
fnord()
# NoMethodError: undefined method `fnord' for main:Object
或者确保解析器(而不是计算器)在使用前解析(而不是执行)赋值,以告诉Ruby它是一个局部变量:

if false
  fnord = 42
end
fnord              #=> nil
为什么实例变量的处理方式不同于局部变量和类变量

实际上不是。它被当作局部变量处理。类层次结构变量的行为不同,局部变量、实例变量和全局变量的行为都相同

还有其他原因吗…类变量不能像那样工作吗

我不知道。对于实例变量,它非常方便,因为与Java不同,例如,实例变量在类定义中声明,因此始终存在于类的每个实例中,而在Ruby中,实例变量不在任何地方声明。一旦分配给他们,他们就会神奇地出现。由于实例变量不一定存在,因此编写使用实例变量的方法如果抛出异常将是一件痛苦的事情

为什么类层次结构变量不同,我不知道。可能是因为没有人使用它们,或者是因为它们通常在类主体中初始化,并且在未初始化时无法访问