Получить значение переменной экземпляра, учитывая его имя

В общем, как я могу получить ссылку на объект, имя которого у меня есть в строке?

В частности, у меня есть список имен параметров (переменные-члены - построены динамически, поэтому я не могу напрямую обращаться к ним).

Каждый параметр - это объект, который также имеет метод from_s.

Я хочу сделать что-то вроде следующего (что, конечно же, не работает...):

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

Ответ 1

Самый идиоматический способ достичь этого:

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

Нет необходимости использовать + или intern; Ruby справится с этим просто отлично. Однако, если вы попадаете в другой объект и вытаскиваете его ивара, есть достаточно хороший шанс, что вы сломали инкапсуляцию.

Если вы явно хотите получить доступ к ivar, вам нужно сделать его доступным. Рассмотрим следующее:

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

В этом случае, если вы сделали Computer.new, вы должны были бы использовать instance_variable_get для доступа к @cpus. Но если вы делаете это, вы, вероятно, имеете в виду для @cpus, чтобы быть общедоступным. Что вам нужно сделать:

class Computer
  attr_reader :cpus
end

Теперь вы можете сделать Computer.new(4).cpus.

Обратите внимание, что вы можете повторно открыть любой существующий класс и сделать приватный ivar в читателе. Поскольку аксессор - это всего лишь метод, вы можете сделать Computer.new(4).send(var_that_evaluates_to_cpus)

Ответ 2

Чтобы получить переменную экземпляра из имени переменной экземпляра, выполните:

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

Это вернет значение переменной экземпляра @paramName