Ruby(和Rails)嵌套模块语法

我想知道以下两个模块之间的区别

# First Example module Parent module Child end end 

 # Second Example module Parent::Child end 

使用第二种方法,似乎必须先定义父模块,否则我会得到一个’未初始化的常量’错误

鉴于此,定义诸如此类的模块然后在语法和文件结构(即文件夹等)方面添加嵌套子元素的首选方法是什么。 非常感谢参考Rails方式。

所有意图和目的的这两个例子是否相同?

在第一个示例中,它定义Parent模块,然后定义Child模块。 正如您所说,第二个示例必须事先定义Parent模块。 再花费一行代码,您可以确保始终使用第一个示例嵌套模块。

对于Rails示例,让我们查看railties / lib / rails / engine.rb文件,该文件重新打开Rails模块 ,然后在其中定义Engine类 。 这可以简单地完成:

 class Rails::Engine 

但也许出于上述原因,也许为了清晰起见,首先定义模块,然后定义内部类。

我更喜欢第二种方法(如果我确定已经定义了Parent),因为它看起来更干净,尤其是 当筑巢很深。

然而,第一种方法有一些优点,尚未讨论的是嵌套模块可以访问封闭模块中任何词法可用的常量。

一般来说,您不希望使用模块Parent :: Child语法定义模块,除非您可以绝对确定Parent已经存在。 如果定义了父模块,则只能使用::语法定义子模块。 在您的示例中,如果执行以下操作,则不会获得未初始化的常量错误。

 module Parent end module Parent::Child end 

似乎Banister的答案也是这种行为的原因:

 ruby-1.9.2-p290 :001 > module A; module A; A.ancestors; end; end => [A::A] ruby-1.9.2-p290 :002 > module A::A; A.ancestors; end => [A] 

内部模块A在外部模块A内部是常数,因此使用第二种方法不可见。

编辑我之前的评论:

这在“Ruby编程语言”(第一版)的7.9“常量查找”中进行了解释。 这里的相关部分是Module.nesting,它不包含第二个示例中的外部模块,因此A只能在全局范围内找到。