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.