Ruby require如何始终加载到顶级范围?

Ruby require如何始终加载到顶级范围?,ruby,Ruby,考虑以下Ruby代码: class A require 'json' end 因为Ruby是逐行解释和执行代码的,所以我希望JSON的作用域是在 然而: irb(main):005:0> A::JSON Traceback (most recent call last): 4: from /usr/bin/irb:23:in `<main>' 3: from /usr/bin/irb:23:in `load' 2: from

考虑以下Ruby代码:

class A
  require 'json'
end
因为Ruby是逐行解释和执行代码的,所以我希望JSON的作用域是在

然而:

irb(main):005:0> A::JSON
Traceback (most recent call last):
        4: from /usr/bin/irb:23:in `<main>'
        3: from /usr/bin/irb:23:in `load'
        2: from /usr/lib/ruby/gems/2.7.0/gems/irb-1.2.1/exe/irb:11:in `<top (required)>'
        1: from (irb):5
NameError (uninitialized constant A::JSON)


irb(main):004:0> JSON
=> JSON
irb(main):005:0>A::JSON
回溯(最近一次呼叫最后一次):
4:from/usr/bin/irb:23:in`'
3:from/usr/bin/irb:23:in'load'
2:from/usr/lib/ruby/gems/2.7.0/gems/irb-1.2.1/exe/irb:11:in`'
1:来自(irb):5
NameError(未初始化的常量A::JSON)
irb(主):004:0>JSON
=>JSON

require
如何始终将gems加载到顶级范围?

实现了
require
,因此它可以访问普通Ruby代码无法访问的内部功能。例如,它可以手动退出其当前作用域,并在顶层执行代码。这就是“如何”

至于“为什么”?想象一下,如果您可以将
require
放入一个特定的范围,这将极易被破坏,因为它会将顶级
self
main
(这是一个
对象
)更改为。。。任何内容(在您的示例中,它将是
A
,它是
)。当您的代码是
require
d时,通常很难预测会发生什么


通过始终在顶层执行加载的代码,结果总是一致的。您可以使用内置的钩子机制(包括、扩展、前置、继承)从加载您的作用域访问特定的
self
s。

在Rubinius中,
Kernel#require
是在纯Ruby(不是在C中)和核心库(不是在VM中)中实现的,但其行为完全相同。因此,许多Ruby实现中的一个碰巧在VM中用C实现它,这一事实并不能解释为什么
require
在所有Ruby实现中的行为方式。不管它在其他Ruby中如何实现,这就是它在标准Ruby中的实现方式。除了对所有已知的实现进行调查之外,我不知道还能如何回答