ruby - 在动态命名的对象上调用方法

时间:2015-02-24 05:24:35

标签: ruby object dynamic instantiation

我有一个字符串数组,表示现有的对象名称。

JoesDev  = Dev.new
MarksDev = Dev.new
SamsDev  = Dev.new

devices=['JoesDev', 'MarksDev', 'SamsDev' ]

我想迭代设备数组,同时在对象上调用一个方法,命名数组中的每个项目。

即;

JoesDev.method_name
MarksDev.method_name
SamsDev.method_name

我该怎么做? THX。

3 个答案:

答案 0 :(得分:1)

devices.each{|name| self.class.const_get(name).method_name}

答案 1 :(得分:0)

一种方法肯定是使用eval,这种方法允许您执行任意字符串,就好像它们是代码一样。

所以,在你的例子中:

var_names.each{ |var_name| eval("#{var_name}.some_method") }

毋庸置疑,将未经过滤的字符串用作代码是非常危险的,非常糟糕的事情™可能会发生!

答案 2 :(得分:0)

您可以使用const_get method from Module让Ruby返回具有给定名称的常量。在您的情况下,它将为您提供的任何设备名称返回Dev实例。

使用.each迭代项目,您的代码可能看起来像

devices.each do |device_name|
  device = self.class.const_get(device_name)
  device.method_name
end

# Which can be shortened to
devices.each{ |dev| self.class.const_get(dev).method_name }

但是,有更好的方法来实现这种类型的东西。最常见的方法是使用Hash。在您的示例中,设备列表可能类似于

devices = {
  joe: Dev.new,
  mark: Dev.new,
  sam: Dev.new
}

然后,迭代设备就像

一样简单
devices.each do |dev|
  dev.method_name
end

# Or
devices.each{ |dev| dev.method_name }

额外:如果您想要有点花哨,可以使用block version of Hash::new来添加新设备非常简单。

# Create the hash
devices = Hash.new{ |hash, key| hash[key] = Dev.new }

# Add the devices
devices['joe']
devices['mark']
devices['sam']

这种哈希的工作方式与上面显示的完全相同,但如果在哈希中找不到给定的密钥,则会创建一个新的条目。因此,这种设计的一个潜在问题是,如果输入错误,您可能会意外添加新设备。例如

devices['jon'] # This would make a new Dev instance, which may be undesirable.