Ruby(和Rails)嵌套模块语法

时间:2010-05-19 19:44:36

标签: ruby-on-rails ruby module

我想知道以下两个模块之间有什么区别

# First Example
module Parent
  module Child
  end
end

# Second Example
module Parent::Child
end

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

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

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

4 个答案:

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