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

ruby - calling a method on a dynamically named object

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

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

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

我想遍历设备数组,同时对数组中每个项目以其命名的对象调用方法。

即;

JoesDev.method_name
MarksDev.method_name
SamsDev.method_name

我该怎么做?谢谢

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

因此,在您的示例中:

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

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

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

您可以使用 const_get method from Module 使 Ruby return 具有给定名称的常量。在您的情况下,它将 return 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.