Diverse variabili si comportano in modo diverso in Ruby, ma nessuna di esse ha bisogno di una dichiarazione esplicita.
Il comportamento più interessante è per le variabili locali: Ruby ti permette di lasciare il ricevitore per un messaggio inviato a self
( self
è il ricevitore implicito), quindi foo()
è la stessa cosa di self.foo()
e consente anche di escludere l'elenco degli argomenti se non ci sono argomenti, quindi foo.bar
è la stessa cosa di foo.bar()
; mettendo insieme i due, otteniamo che foo
è la stessa cosa di self.foo()
, cioè un messaggio invia senza argomenti al ricevitore implicito self
. Potrebbe, tuttavia, essere anche un riferimento alla variabile locale foo
. Questa ambiguità è risolta nel modo seguente: foo
è interpretato come un messaggio di invio, a meno che un assegnamento a foo
sia stato analizzato (ma non necessariamente eseguito ) prima, quindi da quel punto in poi viene interpretato come una variabile locale.
Questa è la cosa più vicina che Ruby deve alla dichiarazione di variabile:
foo
# NameError: undefined local variable or method 'foo'
defined?(foo)
# => nil
def foo; 23 end
foo
# => 23
defined?(foo)
# => 'method'
methods
# => [:foo, …]
if false then foo = 42 end
foo
# => nil
defined?(foo)
# => 'local-variable'
local_variables
# => [:foo]
Si noti che NameError
è not generato perché la variabile locale non è definita, ma poiché Ruby non sa cosa fare dell'espressione: è una variabile locale o una chiamata di metodo?
Le variabili di istanza e le variabili globali si comportano in modo simile, valutano a nil
anche se non sono definite:
@foo
# => nil
defined?(@foo)
# => nil
@foo = 42
@foo
# => 42
defined?(@foo)
# => 'instance-variable'
instance_variables
# => [:@foo]
$foo
# => nil
defined?($foo)
# => nil
$foo = 42
$foo
# => 42
defined?($foo)
# => 'global-variable'
global_variables
# => [:$foo, …]
Le variabili e le costanti della gerarchia di classe si comportano diversamente, aumentano NameError
se non sono definite:
@@foo
# NameError
defined?(@@foo)
# => nil
@@foo = 42
@@foo
# => 42
defined?(@@foo)
# => 'class-variable'
self.class.class_variables
# => [:@@foo]
FOO
# NameError
defined?(FOO)
# => nil
FOO = 42
FOO
# => 42
defined?(FOO)
# => 'constant'
self.class.constants
# => [:FOO]