在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 :(得分: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] }