包含模块如何影响范围?具体来说,在这个例子中:
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
test 1 工作正常,但 test 2 和 test 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
在阅读 book "Metaprogramming Ruby" 后,我开始了解 Ruby 中的作用域.这确实很有启发性。
编辑:回应下面的评论。
类本质上是一个 Ruby 常量(注意它是一个名称大写的对象)。常量在范围内有定义的查找算法。 The Ruby Programming Language O'Reilly 的书在第 7.9 节对此进行了很好的解释。在此 blog post 中也对其进行了简要描述。 .
在任何类或模块之外定义的顶级常量就像顶级方法:它们在 Object 中隐式定义。当从类中引用顶级常量时,它会在搜索继承层次结构时被解析。如果常量在模块定义中被引用,它会在搜索模块的祖先后对 Object 进行显式检查。
这就是为什么在顶层包含 ModuleB 会使 ModuleB 中的类在所有模块、类和方法中可见。
关于Ruby 类、包含和作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7549625/