我想知道以下两个模块之间有什么区别
# First Example
module Parent
module Child
end
end
和
# Second Example
module Parent::Child
end
使用第二种方法,似乎必须事先定义父模块,否则我会得到一个'未初始化的常量'错误
鉴于此,定义诸如此类的模块的首选方法是什么,然后在语法和文件结构(即文件夹等)方面添加嵌套子代。非常感谢参考Rails方式。
这两个例子是否等同于所有意图和目的?
答案 0 :(得分:31)
在第一个示例中,它定义了Parent
模块,然后定义了Child
模块。正如您所说,第二个示例必须事先定义Parent
模块。再花费一行代码,您可以确保使用第一个示例嵌套的模块始终定义。
对于Rails示例,让我们查看 railties / lib / rails / engine.rb 文件,其中re-opens the Rails
module然后是defines an Engine
class。这可以简单地完成:
class Rails::Engine
但也许出于上述原因,也许为了清楚起见,首先定义模块,然后是内部的类。
答案 1 :(得分:13)
我更喜欢第二种方法(如果我确定已经定义了Parent),因为它看起来更干净,尤其是当筑巢很深时。
然而,第一种方法有一些优点,尚未讨论的是嵌套模块可以访问封闭模块中任何词法可用的常量。
答案 2 :(得分:7)
一般来说,您不希望使用模块Parent :: Child语法定义模块,除非您可以绝对确定Parent已经在那里。如果定义了父模块,则只能使用::语法定义子模块。在您的示例中,如果执行以下操作,则不会获得未初始化的常量错误。
module Parent
end
module Parent::Child
end
答案 3 :(得分:3)
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只能在全局范围内找到。