2015-10-14 95 views
0

在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) 

我了解该类应该使用一个数组或哈希。不幸的是,我无法对班级的设计做任何事情,我们必须使用它。

我试图做甚至可能吗?

+0

首先尝试找出哈希实例变量的名称:'pdc.instance_variables' – nsave

回答

1

你既可以尝试调用吸附材料(最好的,因为它给予荣誉封装):

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 

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

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] }