Ruby类,包含和范围

时间:2011-09-26 00:37:23

标签: ruby module scope

包含模块如何影响范围?具体来说,在这个例子中:

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

测试1 工作正常,但测试2 测试3 在没有注释import ModuleB的情况下失败。

  • 为什么ClassA位于ModuleB(测试1)范围内但不在ClassB范围内?
  • 为什么import ModuleBClassA纳入ClassB的范围?

2 个答案:

答案 0 :(得分:7)

关键字模块 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中的类在所有模块,类和方法中都可见。

答案 1 :(得分:0)

原因是(我认为)与绑定有关。我的线索是,以下也行不通:

module ModuleB
 include ModuleA

 class ClassB
  def initialize
   c = ClassA.new
  end
 end

 ClassB.new
end

ClassA并不代表ClassB定义中的任何内容,因为它不是ClassB中的常量 - 模块只包含在其父模块中。进行此更改应该可以使一切正常运行:

module ModuleB
  include ModuleA
  class ClassB
    def initialize
      c = ModuleA::ClassA.new
    end
  end
end