如何确定对ruby的调用需要向全局命名空间添加哪些对象?
假设我有一个文件如何确定对ruby的调用需要向全局命名空间添加哪些对象?,ruby,Ruby,假设我有一个文件example.rb,如下所示: # example.rb class Example def foo 5 end end 我加载的require或require\u relative。如果我不知道定义了example.rb的example,是否有一个列表(除了ObjectSpace)可以检查以查找任何已定义的对象?我试过检查全局变量,但似乎不起作用 谢谢 这取决于“全局名称空间”的含义。Ruby实际上没有“全局”名称空间(除了全局变量)。它有一种“根”名称空间
example.rb
,如下所示:
# example.rb
class Example
def foo
5
end
end
我加载的require
或require\u relative
。如果我不知道定义了example.rb
的example
,是否有一个列表(除了ObjectSpace
)可以检查以查找任何已定义的对象?我试过检查全局变量
,但似乎不起作用
谢谢 这取决于“全局名称空间”的含义。Ruby实际上没有“全局”名称空间(除了全局变量)。它有一种“根”名称空间,即
对象
类。(尽管请注意,对象
可能有一个超类,并混合在内核
中,并且可以从中继承内容。)
“全局”常量只是对象的常量。“全局函数”只是对象的私有实例方法
因此,您可以通过在调用require
/require\u relative
之前和之后检查全局变量
、对象.常量
和对象.实例方法
来合理接近
但是,请注意,根据您对main
的“全局名称空间”(private)单例方法的定义,main的单例方法也可以计算在内,因此您也可以检查这些方法
当然,脚本添加的任何方法在以后调用时都可以向全局范围添加其他内容。例如,以下脚本不向作用域添加任何内容,但调用该方法将:
class String
module MyNonGlobalModule
def self.my_non_global_method
Object.const_set(:MY_GLOBAL_CONSTANT, 'Haha, gotcha!')
end
end
end
但是,严格地说,您要求将“对象”添加到全局名称空间中,常量、方法或变量都不是对象,所以OOOOOO…答案总是“无”?尽管Ruby提供了很多反射方法,但它并没有真正为您提供一个顶级视图,可以识别发生了什么变化(如果有的话)。只有当你有一个特定的目标,你才能深入挖掘
例如:
def tree(root, seen = { })
seen[root] = true
root.constants.map do |name|
root.const_get(name)
end.reject do |object|
seen[object] or !object.is_a?(Module)
end.map do |object|
seen[object] = true
puts object
[ object.to_s, tree(object, seen) ]
end.to_h
end
p tree(Object)
现在,如果树结构中有任何变化,你就有了新的东西。使用seen
作为触发器,可以为此编写一个diff方法
问题是,评估Ruby代码可能不一定会创建它将创建或可能创建的所有类。Ruby允许对任何和所有类进行广泛的修改,在运行时它通常会创建更多类,或者替换和删除其他类。只有强制声明所有模块和类的库才能使用这种技术,我认为这只是其中的一小部分。不,没有。您将不得不使用ObjectSpace。(还有,全局变量和常量不是一回事。)如果你在寻找除“否”之外的另一个答案,也许可以通过构建为什么不想使用ObjectSpace
来解决这个问题,这里有Object.constants
,但这只会让你从根本上定义事物。