匿名模块和class可以嵌套在Ruby中吗?

Can anonymous modules and class be nested in Ruby?

我可以在匿名模块中定义一个匿名 class:

c = nil
m = Module.new do
  c = Class.new
end

m #=> #<Module:0x007fad3a055660>
c #=> #<Class:0x007fad3a0555e8>

以上是否等同于:

m = Module.new
c = Class.new

换句话说:"nesting"的概念真的适用于匿名模块吗?

这与匿名无关。将动态创建的 class 分配给常量使其命名为:

Foo = Class.new # => Foo
foo = Class.new # => #<Class:0x007fe5dd45d650>

但它仍然没有进一步嵌套:

module Bar
  Baz = Module.new do
    p Module.nesting # => [Bar]
  end
end

或者甚至是动态的:

module Quz
  eval 'module Qux; p Module.nesting; end' # => [Quz::Qux, Quz]
end

这是关于作用域门的。


就常量而言,只有两个作用域门——关键字classmodule

嵌套纯粹是语法上完成的。这就是为什么你会感到奇怪:

module Do
  X = 42
end

module Do
  module Re
    p Module.nesting # => [Do::Re, Do]
    p X              # => 42
  end
end

module Do::Mi
  p Module.nesting # => [Do::Mi]
  p X # => uninitialized constant
end

Do.module_eval   { p X } # => uninitialized constant
Do.instance_eval { p X } # => uninitialized constant

因此,如果 Ruby 看到关键字 classmodule,它会进一步嵌套 "current node"。当找到关闭的 end 时,它会在树上向上移动。当一个新常量被定义时,它将它放在当前节点中。