2010-10-26 10 views
12

mismo en Ruby 1.8.7 y 1.9.2:En Ruby, ¿por qué después de comenzar irb, foo.nil? dice error indefinido, y @ foo.nil? da "verdadero", y @@ wah.nil? da error de nuevo?

$ 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 

razón por la variable de instancia tratada de manera diferente a una variable local y la clase?

Respuesta

17

En Ruby, la mayoría de las variables no inicializadas o incluso inexistentes evalúan a nil. Esto es cierto para las variables locales, variables de instancia y variables globales:

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 

Es, sin embargo, no es cierto para las variables jerarquía de clases y constantes:

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

defined? QUUX  #=> nil 
QUUX 
# NameError: uninitialized constant Object::QUUX 

Esta es una pista falsa:

defined? fnord  #=> nil 
local_variables #=> [] 
fnord 
# NameError: undefined local variable or method `fnord' for main:Object 

El motivo por el que aparece un error aquí es no que las variables locales unificadas no se evalúan a nil, es t hat fnord es ambiguo: podría ser enviar un mensaje sin argumento al receptor predeterminado (es decir equivalente a self.fnord()) o un acceso a la variable local fnord.

Con el fin de eliminar la ambigüedad que, es necesario agregar un receptor o una lista de argumentos (aunque estén vacíos) para indicar a Ruby que se trata de un mensaje de envío:

self.fnord 
# NoMethodError: undefined method `fnord' for main:Object 
fnord() 
# NoMethodError: undefined method `fnord' for main:Object 

o asegurarse de que el analizador (no el evaluador) análisis sintácticos (no Ejecuta) una asignación antes del uso, para contar Ruby que es una variable local:

if false 
    fnord = 42 
end 
fnord    #=> nil 

¿por qué la variable de instancia se trató de manera diferente que una variable local y de clase?

No es, en realidad. Se trata igual que una variable local. La variable de jerarquía de clase es la que se comporta de manera diferente, las variables locales, las variables de instancia y las variables globales se comportan todas igual.

hay otras razones & hellip; ¿No pueden las variables de clase comportarse así también?

No lo sé. Por ejemplo, las variables son muy convenientes, ya que a diferencia de Java, por ejemplo, donde las variables de instancia se declaran en la definición de clase y siempre existen para cada instancia de la clase, en Ruby las variables de instancia no se declaran en ningún lado. Simplemente surgen mágicamente a la existencia, tan pronto como se asignan. Dado que las variables de instancia no están necesariamente garantizadas, los métodos de escritura que usan variables de instancia serían una molestia si lanzaran excepciones.

Por qué las variables de jerarquía de clases son diferentes, no tengo idea. Tal vez sea porque nadie los usa de todos modos, o porque generalmente tienden a inicializarse en el cuerpo de la clase y simplemente no se accede cuando no se inicializan.

Cuestiones relacionadas