代码之家  ›  专栏  ›  技术社区  ›  brad

Ruby(和Rails)嵌套模块语法

  •  29
  • brad  · 技术社区  · 15 年前

    # First Example
    module Parent
      module Child
      end
    end
    

    # Second Example
    module Parent::Child
    end
    

    使用第二个方法,看起来好像父模块必须是先前定义的,否则会出现“uninitialized constant”错误

    4 回复  |  直到 15 年前
        1
  •  31
  •   Ryan Bigg Andrés Bonilla    15 年前

    在第一个示例中,它定义了 Parent 模块,然后 Child 起源 之前定义的模块。以多出一行代码为代价,您可以确保通过使用第一个示例嵌套的模块总是被定义的。

    对于Rails示例,让我们看看 铁路/lib/rails/engine.rb re-opens the Rails module 然后 defines an Engine class 在里面。这可以通过简单的方法来实现:

    class Rails::Engine
    

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

        2
  •  13
  •   horseyguy    15 年前

    我更喜欢第二种方法(如果我确定父级已经定义了的话),因为它看起来更干净,特别是当嵌套非常深的时候。

        3
  •  7
  •   jamin4jc    15 年前

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

    module Parent
    end
    
    module Parent::Child
    end
    
        4
  •  3
  •   TauPan    13 年前

    巴尼斯特的回答似乎也是这种行为的原因:

    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,它不包含第二个示例中的外部模块,因此只能在全局范围中找到。