wmo*_*ock 33 ruby inheritance lexical-scope
这是原始SO问题的延续:使用"::"而不是"module ..."来表示Ruby命名空间
在最初的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
Run Code Online (Sandbox Code Playgroud)
有人可以提供一些解释为什么第一个呼叫返回555以及为什么第二个呼叫返回123?
mat*_*att 34
你能想到的每一个外观module Something,class Something或者def something作为一个"门户"进入一个新的范围.当Ruby搜索已被引用的名称的定义时,它首先查找当前作用域(方法,类或模块),如果找不到它,它将返回每个包含"gateway"并搜索那里的范围.
在您的示例中,该方法baz定义为
module Foo
class Bar
def baz
puts FOO
end
end
end
Run Code Online (Sandbox Code Playgroud)
因此,在尝试确定值时FOO,首先Bar检查类,并且由于Bar不包含FOO搜索,因此通过" class Bar网关" 向上移动到Foo包含范围的模块中.Foo确实包含一个常量FOO(555),所以这是你看到的结果.
该方法glorf定义为:
class Foo::Bar
def glorf
puts FOO
end
end
Run Code Online (Sandbox Code Playgroud)
这里的"网关"是class Foo::Bar,所以当在"网关" FOO内部找不到时,Bar通过Foo模块并直接进入顶层,其中有另一个FOO(123)显示的内容.
请注意如何使用class Foo::Bar创建单个"网关",跳过范围Foo,但module Foo; class Bar ...打开两个单独的"网关"
哇,好问题.我能想出的最佳答案是在这种情况下,您正在使用模块来定义命名空间.
看一下这个:
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
Run Code Online (Sandbox Code Playgroud)
所以我的想法是,当你定义:
module Foo
FOO = 555
end
Run Code Online (Sandbox Code Playgroud)
你正在创建FOO名称空间Foo.所以当你在这里使用它时:
module Foo
class Bar
def baz
puts FOO
end
end
end
Run Code Online (Sandbox Code Playgroud)
你在Foo命名空间.但是,当您在以下位置引用它时:
class Foo::Bar
def glorf
puts FOO
end
end
Run Code Online (Sandbox Code Playgroud)
FOO来自默认命名空间(如图所示::FOO).
| 归档时间: |
|
| 查看次数: |
2946 次 |
| 最近记录: |