简体   繁体   English

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM