为什么`include`在顶层表现不同?

odi*_*ity 6 ruby program-entry-point class include

我使用以下钩子检查正在执行包含的模块include Foo:

module Foo
  def self.included(includer)
    puts includer
  end
end
Run Code Online (Sandbox Code Playgroud)

Module#include在模块中(通常使用它)与顶层的行为不同.在模块内部,self是模块,它是一个实例Module.当我打电话include时,模块做,包括是什么样self:

module Bar
  puts self   # => Bar
  include Foo # => includer: Bar
end
Run Code Online (Sandbox Code Playgroud)

在ruby脚本的顶层,selfmain,它是一个实例Object.当我把include在顶层,该模块包括做是Object,之类的东西self:

puts self    # => main
include Foo  # => includer: Object
Run Code Online (Sandbox Code Playgroud)

有人可以解释原因吗?

顶级对象必须是特殊的; 如果我打电话to_s或打电话inspect,它只是说main,但如果我创建另一个对象Object.new并调用to_sinspect打开它,我得到通常的对象表示法:#<Object:0x007fae0a87ac48>.

And*_*rtz 4

main是特殊的,并且有自己的定义include。也就是说,它的 singleton_class 有自己的定义include。为了证明这一点:

irb(main):017:0> method(:include).owner
=> #<Class:#<Object:0x007fc0398c6468>>
irb(main):018:0> self.singleton_class
=> #<Class:#<Object:0x007fc0398c6468>>
Run Code Online (Sandbox Code Playgroud)

include正在考虑的定义是Module

MyClass.method(:include).owner
=> Module
Run Code Online (Sandbox Code Playgroud)

因此,include在“顶层”的行为有所不同,也就是我们main出于最简单的原因而调用的对象:它只是一个与Module#include.