我正在开发一个允许用户自动要求,实例化和注册特定目录中的类的Gem。我只是不确定如何实现这一目标。这就是我到目前为止所提出的......
Dir[Dir.pwd + '/extensions/*.rb'].each do |file|
require file
extension_class = # instantiate the class here
MyApp.extensions << extension_class
end
如何在不知道它叫什么的情况下实例化该类?
答案 0 :(得分:6)
听起来你正在建立一个编写软件扩展的系统。由于扩展类可能在某种程度上相似,例如共享一些常用方法,因此有一个名为Extension
的基类可能是有意义的,所有扩展类都从该基类继承。
实际上,这对所述问题非常有用,因为当用户从您的类继承时,您可以检测它,并将子类添加到列表中。以下是概念代码的一些证明:
class Extension
class << self
attr_reader :list
end
@list = []
def self.inherited(klass)
@list << klass.new
end
end
# The MyExt class would be in another file, loaded by require.
class MyExt < Extension
end
p Extension.list # => [#<MyExt:0xb777d884>]
如果您由于某种原因不想使用子类,那么将Extension
作为模块并使用included
挂钩而不是inherited
同样容易。
就个人而言,我只是删除对.new
的调用,因为我没有理由立即实例化该类,但这取决于你。我只会存储一个类列表。
答案 1 :(得分:1)
这是一个有趣的想法,让我摸不着头脑。我找不到谷歌搜索的直接解决方案,所以我玩了一下语言。我提出了三个基本想法:
我决定最喜欢第一个选项;它不要求您以特定方式构造文件,或者扩充类以便知道它们将以这种方式被要求。这是一个基本的实现,借用你的初始结构:
classes = ObjectSpace.each_object(Class).to_a
Dir[Dir.pwd + '/extensions/*.rb'].each do |file|
require file
changed_classes = ObjectSpace.each_object(Class).to_a
(changed_classes - classes).each do |extension_class|
MyApp.extensions << extension_class
end
classes = changed_classes
end