Kernel#autoload
记录如下:
第一次访问该模块(可能是字符串或符号)时,注册要加载的文件名(使用Kernel :: require)。
"访问"
的定义是什么?我很惊讶地发现"空"类定义触发自动加载。
# a.rb
class A
def foo() end
end
# irb -I .
autoload :A, 'a.rb'
#=> nil
class A; end # supposedly "empty" class ..
#=> nil
A.instance_methods.include?(:foo) # .. is not "empty"!
#=> true
因为我使用了class
关键字,所以我希望上面定义一个"空"班A
。具体来说,我没想到A
的实例会回复foo
。我没想到要自动加载a.rb
。
那么,"访问"的准确定义是什么?触发autoload
?
答案 0 :(得分:3)
在Ruby中,一般来说,类定义代码或任何其他可执行代码之间没有区别。
这意味着,遇到语句后立即调用以下内容:
5.times { puts "Hello" }
以同样的方式,class
的代码在定义后立即执行:
class C
puts "Hello"
end
=> "Hello"
有人可能会怀疑没有执行实例方法,里面的调用。原因是这些方法包含 bindings ,因此在类的实例(对象)上调用(另外,这完全是另一个故事)。
这定义了您问题中的访问。一旦定义了class A
,就会访问。正如Arup在回答中所说,autoload
执行延迟加载,class/module
仅在访问时加载。在Ruby中打开的类会触发class A
中a.rb
的自动加载。
希望这会有所帮助。:)
答案 1 :(得分:2)
Kernel#autoload
会加载。它不会检查是否已经定义了类,或者它是否在中间定义。
来源:Practicing Ruby's "Ways to Load Code",Kernel#autoload
部分。
答案 2 :(得分:1)
我无法从kernel
doc中找出含义,autoload
以与require
类似的方式工作,但它只加载第一个访问常量时指定的文件时间。因此,当您尝试扩展同一个类时,您是第一次访问它,因此它从文件加载定义。
好好阅读(我给它留了很长时间的书签):http://www.rubyinside.com/ruby-techniques-revealed-autoload-1652.html
我修改了你的代码:
# a.rb
puts "I was loaded"
class A
def foo()
end
end
它将显示第一行并告诉您何时加载此文件。
HTH