Working in Ruby, we have to use a 3rd party Framework, which has a class setup something like this:
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.
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):
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. The first argument must be a string or a symbol representing the name of an instance variable including the @
prefix: eg "@thing{i}"
. However you actually want to get the value of an instance variable and then send #bar=
to it. That can be done with 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):
1.upto(numberOfThings) { |i| pdc.public_send("thing#{i}").bar = value[i] }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.