能否使用字符串作为模块来扩展类?- Ruby 2.7.1

3
我正在FreeBSD 12.1上用Ruby 2.7.1进行一些测试。我知道如何使用模块扩展类,例如这样:
class Myclass
  def mymethod
    extend Mymodule
  end
end

但是有没有可能用类似这样的东西获得相同的结果:

class Myclass
  def mymethod
    var = "Mymodule"
    extend var
  end
end

如果我像这样做,那么我肯定会得到一个错误,因为extend指向字符串而不是模块。
以下是一些解释 - 这在以下应用程序中非常有用:
假设您有一个带有许多Ruby脚本的文件夹,它们都是具有明显名称的模块。例如,abcd.rb将包含模块Abcd。因此,我创建了一个文件列表并将其保存在数组中。然后,我可以加载或需要在此数组中列出的所有这些文件。由于模块的名称是可预测的,因此我只需执行一些.sub,.chop和.capitalize方法来获取数组索引的可行结果,该结果看起来就像模块的名称。
想法是创建一种平均方式,以便自动扩展我的主类到所有这些模块。在这个想法中,添加到文件夹中的任何模块都将自动加载并准备好使用。
但是,由于我的数组操作的结果不是“纯”模块名称,而是字符串,所以我就卡在这里了。
那么,有没有办法实现这一点(也许我使用了错误的路径),还是不可能的?
提前感谢!

1
好问题。我可以想象那种技术会很有用。 - Cary Swoveland
2
你可能想要查看Module#autoload,以便更轻松地实现加载。你可以使用Dir.glob.map,然后设置自动加载并返回符号和标签,最后加上each(&method(:extend))。我现在没有足够的时间来撰写完整的答案,否则我会的。 - engineersmnky
1个回答

4

你不能扩展“任意字符串(arbitrary string)”,但是你可以先将其转换为一个“模块(module)”:

class Myclass
  def mymethod
    var = "Mymodule"
    extend self.class.const_get(var)
  end
end

const_get 可以轻松解析简单的模块名称,如 XX::Y

此外,在与 Rails 捆绑在一起的 ActiveSupport 中,还有一个名为 constantize 的方法,它执行类似的操作:

extend var.constantize

@Stefan 那是个好消息。也许我被一个旧版本的 Ruby 弄糊涂了,它没有这样做。 - tadman
3
直接调用 Object.const_get 和 OP 的写法并不等价,因为你明确地从 Object 开始查找(它也是顶层,所以在 KernelBasicObject 除外的情况下,实际上也在那里结束查找)。为了使你的代码与 OP 的代码等价,你只需使用 const_get,或者由于这是一个实例方法,而使用 self.class.const_get,从接收器的类开始查找,而不是从 Object 开始。 - Jörg W Mittag
@JörgWMittag 为了保留解析作用域?好主意。 - tadman
是的。例如,在周围的词法作用域中无法解析常量可能会令人惊讶。 - Jörg W Mittag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接