获取给定名称的实例变量的值


99

通常,如何获得对字符串中具有其名称的对象的引用?

更具体地说,我有一个参数名称列表(成员变量-动态构建的,因此我不能直接引用它们)。

每个参数都是一个对象,也有一个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

Answers:


179

实现此目的的最惯用的方法是:

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

无需使用+intern; Ruby会很好地处理这个问题。但是,如果您发现自己进入另一个对象并拉出它的ivar,则很有可能破坏了封装。

如果您明确想要访问ivar,则正确的做法是使其成为访问器。考虑以下:

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

在这种情况下,如果您这样做了Computer.new,则将不得不使用instance_variable_getat @cpus。但是,如果您这样做,则可能意味着@cpus要公开。您应该做的是:

class Computer
  attr_reader :cpus
end

现在您可以做Computer.new(4).cpus

请注意,您可以重新打开任何现有的类,并将私有ivar制成阅读器。由于访问器只是一种方法,因此您可以执行Computer.new(4).send(var_that_evaluates_to_cpus)


instance_variable_get(“ @#{name}”)不会返回变量的值吗?我需要对实际对象的引用。我最终进行了重写,因此,我没有按照我想要的顺序包含多个变量和名称顺序的数组,而是将参数本身放入了数组中(设计决策是每次通过搜索数组来访问变量还是通过使用其名称仅在需要时使用的其他数组)
LK__

否:instance_variable_get(“ @#{name}”)返回实际对象。
Yehuda Katz

揭开死线程的内容,以使其更加清晰。完整的示例为:类Computer attr_read:cpus def new(cpus)@cpus = cpus end end吗?
Nicolas de Fontenay

“但是,如果您发现自己碰到另一个对象并拉出它的ivar,则很有可能破坏了封装。” 我们如何闯入另一个对象的ivar?
RubyMiner 2015年

9

要从实例变量的名称获取实例变量,请执行以下操作:

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

这将返回实例变量的值 @paramName


动态创建类时,我有一个实例变量名称数组(我需要此列表,因为我需要按一定顺序处理它们)。通过使用此名称,我想获得对该变量的引用。
LK__

1
我有一个字符串“ paramName”,需要引用@paramName
LK__

1
好。我建议您编辑问题以准确说明这两个评论。
Daniel Lucraft

2
同样,这与反序列化无关。更好的标题可能是“获取给定名称的实例变量的值”或其他名称。
Daniel Lucraft

您始终可以添加并添加模块,:attr_reader varname以便随后可以以更简洁,更简洁的方式访问变量。
ocodo 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.