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只能在全局范围内找到。