这是这个原始问题的延续: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吗?
发布于 2013-03-04 01:02:01
您可以将module Something、class Something或def something的每次出现视为进入新作用域的“网关”。当Ruby搜索已被引用的名称的定义时,它首先在当前作用域(方法、类或模块)中查找,如果在当前作用域中找不到,它将返回包含“gateway”的每个作用域,并在那里搜索作用域。
在您的示例中,方法baz被定义为
module Foo
class Bar
def baz
puts FOO
end
end
end因此,当尝试确定FOO的值时,首先检查类Bar,由于Bar不包含网关,因此搜索将通过“class Bar FOO”向上移动到包含范围的Foo模块。Foo确实包含一个常量FOO (555),因此这是您看到的结果。
方法glorf的定义如下:
class Foo::Bar
def glorf
puts FOO
end
end这里的“网关”是class Foo::Bar,所以当在Bar中找不到FOO时,“网关”通过Foo模块,直接进入顶层,在那里有另一个FOO (123),这就是所显示的内容。
注意使用class Foo::Bar如何创建一个“网关”,跳过Foo的作用域,但module Foo; class Bar ...打开两个独立的“网关”
发布于 2013-02-28 03:14:45
哇,问得好。我能想到的最好的答案是,在这种情况下,您使用模块来定义名称空间。
看看这个:
FOO = 123
module Foo
FOO = 555
end
module Foo
class Bar
def baz
puts FOO
end
def glorf3
puts ::FOO
end
end
end
class Foo::Bar
def glorf2
puts Foo::FOO
end
def glorf
puts FOO
end
end
puts Foo::Bar.new.baz # -> 555
puts Foo::Bar.new.glorf # -> 123
puts Foo::Bar.new.glorf2 # -> 555
puts Foo::Bar.new.glorf3 # -> 123所以我的想法是,当你定义:
module Foo
FOO = 555
end您正在Foo的名称空间中创建FOO。所以当你在这里使用它的时候:
module Foo
class Bar
def baz
puts FOO
end
end
end您位于Foo命名空间中。但是,当您在中引用它时:
class Foo::Bar
def glorf
puts FOO
end
endFOO来自默认名称空间(如::FOO所示)。
发布于 2013-03-02 06:16:52
第一个调用:
puts Foo::Bar.new.baz # -> 555打印调用类Foo::Bar的实例的方法baz的结果
请注意,Foo::Bar#baz definition 实际上是FOO上的闭包。下面是ruby的作用域规则:
在
中找到它
第二个调用:
puts Foo::Bar.new.glorf # -> 123打印调用类Foo::Bar的实例的方法glorf的结果
注意,这次Foo::Bar#glorf定义也是FOO上的一个闭包,但是如果我们遵循ruby的作用域规则,你会注意到这个时候关闭的值是::FOO (顶级作用域FOO),如下所示:
中找到的
https://stackoverflow.com/questions/15119724
复制相似问题