如何在模块中加载未知类?
Posted
技术标签:
【中文标题】如何在模块中加载未知类?【英文标题】:How to load a unknown class in a module? 【发布时间】:2011-07-23 10:15:09 【问题描述】:我有一些 rb 文件,都具有相同的结构:
class RandomName < FooBar
end
randomname 是一个随机类名,在每个 rb 文件中都会发生变化,但都继承自 Foobar。
如何从 rb 文件中加载所有 randomclass?
【问题讨论】:
Best way to require all files from a directory in ruby ? 的可能重复项 不!因为我知道如何要求所有文件,但我不知道如何在里面获取类的实例!如果我不知道班级名称 【参考方案1】:您可以在 FooBar 类中定义一个名为 inherited
的方法。看here
class FooBar
def self.inherited(subclass)
puts "New subclass: #subclass"
end
end
每次创建子类时,都会在回调中得到它。然后你可以对所有这些子类做任何你想做的事情。
【讨论】:
【参考方案2】:我认为解决方案有两个部分:
如何动态实例化一个类
一个。使用String#constantize
from ActiveSupport
klass = "SomeNamespace::SomeClassName".constantize
klass.new
b.使用Module#const_get
(不处理命名空间)
klass = const_get(:SomeClassName)
klass.new
如何检测类名
在 ruby 中广泛遵循的约定是以文件包含的类命名文件,因此 random_name.rb
将包含 RandomName
类。如果您遵循此约定,那么您可以执行以下操作:
Dir["/path/to/directory/*.rb"].each do |file|
require file
file_name = File.basename(file.path, '.rb')
# using ActiveSupport for camelcase and constantize
file_name.camelcase.constantize.new
end
我认为您应该解释您要完成的工作。您采用的方法似乎非常规,并且可能有一种更有效的方法来实现您的目标,而无需执行所有这些文件加载和具有随机名称的类的动态实例化。
请记住,仅仅因为 ruby 让您做某事,并不意味着实际去做就是一个好主意!
【讨论】:
【参考方案3】:我有类似的要求,将类名作为字符串传入。 require 的一个技巧是它不必在开头,所以我更喜欢只加载我需要的类。
我使用 eval 是因为它没有任何 Rails 依赖项(我在这里编写纯 Ruby 代码)。
以下依赖于约定(类在同名文件中),但如果您确实知道类和文件,这种方法的优点是不需要目录中的每个文件,只需动态加载在您需要的时候使用它。
klass = "classname"
begin
# Load the file containing the class from same directory I'm executing in
require_relative klass # Or pass a local directory like "lib/#klass"
# Use eval to convert that string to a Constant (also capitalize it first)
k = eval(klass.capitalize).new
rescue
# Do something if the convention fails and class cannot be instantiated.
end
k.foo # Go ahead and start doing things with your new class.
【讨论】:
以上是关于如何在模块中加载未知类?的主要内容,如果未能解决你的问题,请参考以下文章
Xampp:作曲家安装问题:模块 openssl 已在第 0 行的未知中加载