这是原始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 Something
,class Something
或def 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 ...
打开两个单独的“网关”