Perché il metodo non mostra @var_one
rispetto alla variabile a
?Variabili di istanza e classe Singleton
a = Object.new
def a.my_eval; yield end
a.my_eval { @var_one = 1 }
a.instance_variables
# => []
instance_variables
# => [@var_one]
Perché il metodo non mostra @var_one
rispetto alla variabile a
?Variabili di istanza e classe Singleton
a = Object.new
def a.my_eval; yield end
a.my_eval { @var_one = 1 }
a.instance_variables
# => []
instance_variables
# => [@var_one]
Si dovrebbe usare instance_eval
:
a.instance_eval { @var_one = 1 }
=> 1
a.instance_variables
=> [:@var_one]
Quando si utilizza ordinaria eval
, si definisce il variabile di istanza nel contesto attuale self
, se lo si fa in IRB, è l'oggetto main
:
a.eval { self }
=> main
Quindi, è possibile modificare il metodo di a.eval
eseguendo un blocco in un contesto di un'istanza:
def a.eval(&block)
instance_eval &block
end
a.eval { @a = 1 }
=> 1
a.instance_variables
=> [:@a]
Se il vostro obiettivo è quello di impostare una variabile di istanza a livello di codice, è possibile utilizzare:
a.instance_variable_set(:@var_one, 1)
Si deve sapere la differenza tra eval
e instance eval
:
Kernel.eval
valuta una stringa nella corrente contesto o il contesto del dato vincolo. È il metodo utilizzato da IRB per elaborare i tuoi input. Permette di definire nuove variabili e metodi per il contesto attuale.
Object.instance_eval
valuta una stringa (o il blocco specificato) nel contesto di una certa istanza di classe e consente quindi l'accesso diretto alle proprietà della classe senza attr
o attr_accessor
. Permette di definire nuovi metodi per un'istanza.
Quindi:
a.instance_eval { @var_one = 1 }
a.instance_variables
# => [:@var_one]
@mhaseev definito la propria 'eval', quindi non utilizza' Kernel.eval'. Penso che la risposta sia più direttamente correlata al binding del blocco e al modo in cui 'yield' o' ProC# call 'interagiscono con quel binding. –