In Ruby werden die meisten nicht initialisierten oder sogar nicht existierenden Variablen auf ausgewertet. Dies gilt sowohl für lokale Variablen, Instanzvariablen und globale Variablen:
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 ist aber nicht wahr, für Klassenhierarchie Variablen und Konstanten:
defined? @@wah #=> nil
@@wah
# NameError: uninitialized class variable @@wah in Object
defined? QUUX #=> nil
QUUX
# NameError: uninitialized constant Object::QUUX
Dies ist ein roter Hering:
defined? fnord #=> nil
local_variables #=> []
fnord
# NameError: undefined local variable or method `fnord' for main:Object
Der Grund, warum Sie hier einen Fehler erhalten, ist nicht dass unitialized lokale Variablen nicht nil
auswerten, es ist t Hut fnord
ist mehrdeutig: es könnte sein entweder eine argumentlose Nachricht an den Standardempfänger (d. h. äquivalent zu self.fnord()
) oder ein Zugriff auf die lokale Variable fnord
.
Damit eindeutig zu machen, benötigen Sie einen Empfänger oder eine Argumentliste (auch wenn sie leer) hinzufügen Ruby zu sagen, dass es eine Nachricht zu senden ist:
self.fnord
# NoMethodError: undefined method `fnord' for main:Object
fnord()
# NoMethodError: undefined method `fnord' for main:Object
oder sicherstellen, dass die Parser (nicht die Auswerter) parst ( nicht ausführt) eine Zuordnung vor der Verwendung, Rubin zu sagen, dass es sich um eine lokale Variable ist:
if false
fnord = 42
end
fnord #=> nil
Warum die Instanzvariable anders behandelt als eine lokale Variable und eine Klassenvariable?
Es ist nicht, eigentlich. Es wird genauso behandelt wie eine lokale Variable. Die Klassenhierarchievariable verhält sich unterschiedlich, lokale Variablen, Instanzvariablen und globale Variablen verhalten sich alle gleich.
gibt es andere Gründe & hellip; Können sich Klassenvariablen nicht so verhalten?
Ich weiß es nicht. Zum Beispiel ist es sehr praktisch, da im Gegensatz zu Java, wo beispielsweise Instanzvariablen in der Klassendefinition deklariert werden und somit immer für jede Instanz der Klasse existieren, in Ruby Instanzvariablen nirgends deklariert werden. Sie entstehen einfach magisch, sobald sie zugewiesen sind. Da Instanzvariablen nicht notwendigerweise garantiert existieren, wäre das Schreiben von Methoden, die Instanzvariablen verwenden, ein Schmerz, wenn sie Ausnahmen auslösen.
Warum Klassenhierarchievariablen sind anders, ich habe keine Ahnung. Vielleicht liegt es daran, dass sie von niemandem verwendet werden oder weil sie im Allgemeinen dazu neigen, im Klassenkörper initialisiert zu werden und einfach nicht aufgerufen werden, wenn sie nicht initialisiert werden.