包含模块如何影响范围?具体来说,在这个例子中:
module ModuleA
class ClassA
def initialize
puts "test passed"
end
end
end
module ModuleB
include ModuleA
# test 1
C = ClassA.new
class ClassB
def initialize
c = ClassA.new
end
end
end
# test 2 and 3 fail without this
#include ModuleB
module ModuleC
# this doesn't help
include ModuleB
# test 2
ClassB.new
# test 3
ModuleB::ClassB.new
end
Run Code Online (Sandbox Code Playgroud)
测试1工作正常,但测试2和测试3失败而没有注释掉import ModuleB.
ClassA在ModuleB(测试1)范围内但不在ClassB?import ModuleB把ClassA成范围在ClassB?关键字class,module和def是所谓的"范围门".他们创造了新的范围.
#!/usr/bin/env ruby
module ModuleA
class ClassA
def initialize
puts "test passed"
end
end
end
module ModuleB
include ModuleA
# test 1
c = ClassA.new # this works as ModuleA has been included into this module
class ClassB # class is a scope gate, creates new scope
def initialize # def is a scope gate, creates new scope
c = ModuleA::ClassA.new # must fully qualify ClassA
end
end
ClassB2 = Class.new do # no scope gate
define_method :initialize do # no scope gate
c = ClassA.new # this works, no need to fully qualify
end
end
end
b = ModuleB::ClassB.new
b2 = ModuleB::ClassB2.new
Run Code Online (Sandbox Code Playgroud)
在阅读"Metaprogramming Ruby"一书后,我开始了解Ruby的范围.这真的很有启发性.
编辑:回应下面的评论.
一个类本质上是一个Ruby常量(注意它是一个大写名称的对象).常量在范围内具有已定义的查找算法.Ruby编程语言 O'Reilly的书在第7.9节中对此进行了详细解释.在这篇博文中也简要描述了它.
在任何类或模块之外定义的顶级常量类似于顶级方法:它们在Object中隐式定义.当从类中引用顶级常量时,在搜索继承层次结构期间解析它.如果在模块定义中引用常量,则在搜索模块的祖先后会对Object进行显式检查.
这就是为什么在顶层包含ModuleB使得ModuleB中的类在所有模块,类和方法中都可见.