当使用 :: 指定模块时,为什么 Ruby 在更高的范围内找不到 类?

Why doesn't Ruby find classes in a higher scope when module is specified using ::?

我刚刚被困在这个问题上有一段时间了。拿下这个基地:

module Top
  class Test
  end

  module Foo
  end
end

稍后,我可以在扩展 TestFoo 中定义 类,方法是:

module Top
  module Foo
    class SomeTest < Test
    end
  end
end

但是,如果我尝试通过使用 :: 指定模块来最小化缩进:

module Top::Foo
  class Failure < Test
  end
end

这失败了:

NameError: uninitialized constant Top::Foo::Test

这是一个错误,还是只是 Ruby 解析变量名称的方式的逻辑结果?

这是预料之中的。使用 :: 更改常量查找的范围并期望 Test 定义在 Top::Foo.

要获得预期的结果,您可以这样写:

module Top::Foo
  class SomeTest < Top::Test
  end
end

或:

module Top
  class Foo::SomeTest < Test
  end
end

甚至:

class Top::Foo::SomeTest < Top::Test
end

Is this a bug, or is it just a logical consequence

这是一个 "quirk"。有些人认为这是一个错误。

用于查找未解析常量的父作用域由模块嵌套决定。碰巧的是,当您使用 module Top::Foo 时,它只会创建一层嵌套而不是两层。观察:

module Top
  module Foo
    class SomeTest
      Module.nesting # => [Top::Foo::SomeTest, Top::Foo, Top]
    end
  end
end

module Top::Foo
  class SomeTest
    Module.nesting # => [Top::Foo::SomeTest, Top::Foo]
  end
end