这是原始SO问题的延续:Using "::" instead of "module ..." for Ruby namespacing

在最初的SO问题中,这是我仍然难以理解的情况:

FOO = 123

module Foo
  FOO = 555
end

module Foo
  class Bar
    def baz
      puts FOO
    end
  end
end

class Foo::Bar
  def glorf
    puts FOO
  end
end

puts Foo::Bar.new.baz    # -> 555
puts Foo::Bar.new.glorf  # -> 123

有人可以在第一个电话为何返回555和第二个电话为何返回123背后提供一些解释吗?

最佳答案

您可以将module Somethingclass Somethingdef something的每种外观都视为进入新范围的“网关”。当Ruby搜索被引用的名称的定义时,它首先在当前作用域(方法,类或模块)中查找,如果找不到,它将在每个包含“网关”的位置返回并搜索那里的范围。

在您的示例中,方法baz定义为

module Foo
  class Bar
    def baz
      puts FOO
    end
  end
end

因此,在尝试确定FOO的值时,首先会检查Bar类,并且由于Bar不包含FOO,因此搜索将通过“class Bar网关”向上移动到包含范围的Foo模块中。 Foo确实包含常量FOO(555),所以这是您看到的结果。

方法glorf定义为:
class Foo::Bar
  def glorf
    puts FOO
  end
end

这里的“网关”是class Foo::Bar,因此,当在FOO中未找到Bar时,“网关”将通过Foo模块并直接进入顶层,在那里显示另一个FOO(123)。

请注意,如何使用class Foo::Bar跳过Foo的范围来创建单个“网关”,但是module Foo; class Bar ...打开两个单独的“网关”

07-24 09:50
查看更多