用于访问Ruby中的类方法的动态变量

时间:2015-10-14 11:29:00

标签: ruby dynamic-variables

在Ruby中工作,我们必须使用第三方框架,其类设置如下:

class Foo 

    attr_accessor :bar

    def initialize() 
    end

end

class Poorly_Designed_Class

    attr_accessor :thing1
    attr_accessor :thing2
    attr_accessor :thing3
    attr_accessor :thing4
    attr_accessor :thing5

    # through :thing_n .. number defined at runtime

    def initialize()
        @thing1 = Foo.new
        @thing2 = Foo.new
        @thing3 = Foo.new
        @thing4 = Foo.new
        @thing5 = Foo.new
    end

end

我不知道有多少"事情"直到运行时间。可能有5个或者他们可能是50个。

我想做的是:

pdc = Poorly_Designed_Class.new
for i in 0..numberOfThings do
    pdc."thing#{i}".bar = value[i]
end

上述方法无效。

我也试过通过以下方式访问它:

instance_variable_set("pdc.thing#{i}.bar",value)

我知道该类应该使用数组或散列。不幸的是,我无法对课程的设计方式做任何事情,我们必须使用它。

我试图做的甚至可能吗?

2 个答案:

答案 0 :(得分:1)

你可以尝试调用getter(最好是因为它尊重封装):

pdc = PoorlyDesignedClass.new
1.upto(number_of_things.times do |i|
  pdc.public_send(:"thing#{i}").bar = value[i]
end

或获取实例变量(不太优选,因为它打破了封装):

pdc = PoorlyDesignedClass.new
1.upto(number_of_things) do |i|
  pdc.instance_variable_get(:"@thing#{i}").bar = value[i]
end

所以,你走在正确的轨道上,你的代码只有两个问题:实例变量名称以@符号开头,.不是标识符中的合法字符。< / p>

答案 1 :(得分:0)

您错误地使用了Object#instance_variable_set。第一个参数必须是字符串或表示实例变量名称的符号,包括@前缀:例如"@thing{i}"。但是,您实际上希望获取实例变量的值,然后将#bar=发送给它。这可以通过Object#instance_variable_get完成:

1.upto(numberOfThings) { |i| pdc.instance_variable_get("@thing#{i}").bar = value[i] }

这有点长,因为attr_acessor :thingX定义了getter方法,通常最好用Object#public_send调用它们而不是直接访问实例变量(getter方法除了返回一个值之外还可以做其他事情):

1.upto(numberOfThings) { |i| pdc.public_send("thing#{i}").bar = value[i] }