[英]Dynamic Variables to access class methods in Ruby
Working in Ruby, we have to use a 3rd party Framework, which has a class setup something like this: 在Ruby中工作,我们必须使用第3方框架,该框架具有类似以下内容的类设置:
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
I don't know how many "things" there are until run time. 我不知道在运行时有多少“东西”。 there could be 5 or their could be 50.
可能是5个或可能是50个。
What I would like to do is something like: 我想做的是这样的:
pdc = Poorly_Designed_Class.new
for i in 0..numberOfThings do
pdc."thing#{i}".bar = value[i]
end
The above doesn't work. 上面的方法不起作用。
I've also tried accessing it via: 我也尝试通过以下方式访问它:
instance_variable_set("pdc.thing#{i}.bar",value)
I understand that the class should be using an array or hash. 我知道该类应使用数组或哈希。 Unfortunately I can't do anything about how the class is designed and we have to use it.
不幸的是,我对类的设计无能为力,我们必须使用它。
Is what i'm trying to do even possible? 我要做什么甚至有可能吗?
You could either try to call the getter (preferably, since it honors encapsulation): 您可以尝试调用getter(最好是,因为它支持封装):
pdc = PoorlyDesignedClass.new
1.upto(number_of_things.times do |i|
pdc.public_send(:"thing#{i}").bar = value[i]
end
or get the instance variable (less preferred, since it breaks encapsulation): 或获取实例变量(不建议使用,因为它破坏了封装):
pdc = PoorlyDesignedClass.new
1.upto(number_of_things) do |i|
pdc.instance_variable_get(:"@thing#{i}").bar = value[i]
end
So, you were on the right track, there were just two problems with your code: instance variable names start with an @
sign, and .
因此,您处在正确的轨道上,您的代码只有两个问题:实例变量名称以
@
符号开头,而.
is not a legal character in an identifier. 不是标识符中的合法字符。
You're using Object#instance_variable_set
incorrectly. 您使用的
Object#instance_variable_set
错误。 The first argument must be a string or a symbol representing the name of an instance variable including the @
prefix: eg "@thing{i}"
. 第一个参数必须是字符串或符号,代表包含
@
前缀的实例变量的名称:例如"@thing{i}"
。 However you actually want to get the value of an instance variable and then send #bar=
to it. 但是,您实际上想获取实例变量的值,然后将
#bar=
发送给它。 That can be done with Object#instance_variable_get
: 可以使用
Object#instance_variable_get
:
1.upto(numberOfThings) { |i| pdc.instance_variable_get("@thing#{i}").bar = value[i] }
That's a bit long and since attr_acessor :thingX
defines getter methods, it's usually preferable to call them with Object#public_send
instead of directly accessing the instance variable (a getter method might do something else than just returning a value): 这有点长,并且因为
attr_acessor :thingX
定义了getter方法,通常最好使用Object#public_send
来调用它们,而不是直接访问实例变量(getter方法除了返回值之外还可以做其他事情):
1.upto(numberOfThings) { |i| pdc.public_send("thing#{i}").bar = value[i] }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.