2009-07-02 3 views
82

In generale, come posso ottenere un riferimento a un oggetto di cui ho il nome in una stringa?Ottieni il valore di una variabile di istanza data il suo nome

In particolare, ho una lista dei nomi dei parametri (le variabili membro - costruite dinamicamente, quindi non posso farvi riferimento direttamente).

Ogni parametro è un oggetto che ha anche un metodo from_s.

voglio fare qualcosa di simile a quanto segue (che ovviamente non funziona ...):

define_method(:from_s) do | arg | 
    @ordered_parameter_names.each do | param | 
     instance_eval "field_ref = @#{param}" 
     field_ref.from_s(param) 
    end 
end 

risposta

157

il modo più idiomatica realizzare questo è:

some_object.instance_variable_get("@#{name}") 

Non è necessario utilizzare + o intern; Ruby lo gestirà bene. Tuttavia, se ti ritrovi a raggiungere un altro oggetto e ad estrarre il suo ivar, ci sono buone probabilità che tu abbia rotto l'incapsulamento.

Se si desidera accedere esplicitamente a un ivar, la cosa giusta da fare è renderlo un accessorio. Si consideri il seguente:

class Computer 
    def new(cpus) 
    @cpus = cpus 
    end 
end 

In questo caso, se l'avete fatto Computer.new, si sarebbe costretti ad usare instance_variable_get per arrivare a @cpus. Ma se lo fai, probabilmente intendi che lo @cpus sia pubblico. Che cosa si dovrebbe fare è:

class Computer 
    attr_reader :cpus 
end 

ora si può fare Computer.new(4).cpus.

Si noti che è possibile riaprire qualsiasi classe esistente e creare un ivar privato in un lettore. Dal momento che un accessor è solo un metodo, puoi fare Computer.new(4).send(var_that_evaluates_to_cpus)

+0

Does instance_variable_get ("@ # {nome}") restituisce il valore della variabile? Ho bisogno di un riferimento all'oggetto reale. Ho finito per riscrivere quindi invece di avere molte variabili + un array con i nomi nell'ordine che volevo, ho messo i parametri stessi nell'array (la decisione progettuale era se accedere alle variabili ogni volta cercando l'array o ottimizzando avendo un array addizionale con i loro nomi che verrebbe utilizzato solo quando necessario) –

+0

No: instance_variable_get ("@ # {nome}") restituisce l'oggetto reale. –

+0

Scoprire il filo morto per un po 'di chiarezza. L'esempio completo sarebbe: Classe computer attr_read: CPU def nuova (CPU) @cpus = CPU fine fine ? –

7

Per ottenere una variabile di istanza dal nome di una variabile di istanza fare:

name = "paramName" 
instance_variable_get(("@" + name).intern) 

questo riporta il valore della variabile di istanza @paramName

+0

Mentre creo una classe dinamicamente, ho una matrice dei nomi delle variabili di istanza (ho bisogno di questa lista perché devo gestirli in un certo ordine). Usando questo nome, voglio ottenere un riferimento alla variabile. –

+1

Ho una stringa "paramName" e ho bisogno di un riferimento a @paramName –

+1

OK. Ti consiglio di modificare la tua domanda per dire esattamente quei due commenti. –