web-dev-qa-db-fra.com

Obtenir la valeur d'une variable d'instance en fonction de son nom

En général, comment puis-je obtenir une référence à un objet dont j'ai le nom dans une chaîne?

Plus précisément, j'ai une liste des noms de paramètres (les variables membres - construites de manière dynamique pour que je ne puisse pas y faire référence directement).

Chaque paramètre est un objet qui a aussi un from_s méthode.

Je veux faire quelque chose comme ce qui suit (ce qui bien sûr ne fonctionne pas ...):

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

La manière la plus idiomatique d’y parvenir est:

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

Il n'est pas nécessaire d'utiliser + Ou intern; Ruby résoudra cela très bien. Cependant, si vous vous retrouvez à toucher un autre objet et à sortir son ivar, il y a de bonnes chances que vous ayez une encapsulation brisée.

Si vous voulez explicitement accéder à un ivar, la meilleure chose à faire est d'en faire un accesseur. Considérer ce qui suit:

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

Dans ce cas, si vous utilisiez Computer.new, Vous seriez obligé d'utiliser instance_variable_get Pour obtenir une valeur de @cpus. Mais si vous faites cela, vous voulez probablement dire que @cpus Soit public. Ce que vous devriez faire est:

class Computer
  attr_reader :cpus
end

Vous pouvez maintenant faire Computer.new(4).cpus.

Notez que vous pouvez rouvrir any la classe existante et transformer un ivar privé en un lecteur. Puisqu’un accesseur n’est qu’une méthode, vous pouvez faire Computer.new(4).send(var_that_evaluates_to_cpus)

171
Yehuda Katz

Pour obtenir une variable d'instance à partir du nom d'une variable d'instance, procédez comme suit:

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

Ceci renverra la valeur de la variable d'instance @paramName

9
Daniel Lucraft