在ruby中,什么用法会触发内核#autooload?

时间:2014-06-06 18:14:37

标签: ruby

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

3 个答案:

答案 0 :(得分:3)

在Ruby中,一般来说,类定义代码或任何其他可执行代码之间没有区别。

这意味着,遇到语句后立即调用以下内容:

5.times { puts "Hello" }

以同样的方式,class的代码在定义后立即执行:

class C
  puts "Hello"
end
=> "Hello"

有人可能会怀疑没有执行实例方法,里面的调用。原因是这些方法包含 bindings ,因此在类的实例(对象)上调用(另外,这完全是另一个故事)。

这定义了您问题中的访问。一旦定义了class A,就会访问。正如Arup在回答中所说,autoload执行延迟加载class/module仅在访问时加载。在Ruby中打开的类会触发class Aa.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