2010-05-19 11 views
27

Me pregunto cuál es la diferencia entre los dos módulos siguientesRuby (y Pasamanos) sintaxis módulo de anidado

# First Example 
module Parent 
    module Child 
    end 
end 

y

# Second Example 
module Parent::Child 
end 

Utilizando el segundo método, parece como si el Padre el módulo debe definirse previamente; de ​​lo contrario, aparece un error de 'constante no inicializada'

Dado esto, ¿cuál es la forma preferida de definir módulos como este y luego agregar hijos anidados con re gards a la sintaxis y la estructura del archivo (es decir. carpetas, etc.). La referencia a un camino de Rails sería muy apreciada.

¿Son estos dos ejemplos equivalentes para todos los propósitos?

Respuesta

31

En el primer ejemplo, define el módulo Parent y luego el módulo Child. El segundo ejemplo, como dices tú mismo, debe tener el módulo Parent definido previamente. A expensas de una línea más de código, se asegurará de que siempre se definirá el módulo en el que se anida utilizando el primer ejemplo.

Para un ejemplo rieles veamos en el railties/lib/rieles/engine.rb fichero que re-opens the Rails module y luego defines an Engine class dentro de ella. Esto podría haberse hecho con sencillez:

class Rails::Engine 

Pero en lugar tal vez por las razones expuestas anteriormente y quizás también por el bien de la claridad, el módulo se definió en primer lugar, a continuación, la clase en el interior.

+1

Una nota importante es lo que @banister mencionó, que el acceso a las constantes es diferente. – thomthom

7

En general, no desea definir un módulo utilizando la sintaxis del módulo Parent :: Child a menos que pueda estar absolutamente seguro de que Parent ya está allí. Un submódulo solo se puede definir utilizando la sintaxis :: si el módulo principal está definido. En su ejemplo, si hace lo siguiente, no obtendrá un error constante no inicializado.

module Parent 
end 

module Parent::Child 
end 
13

Yo prefiero el segundo método (si estoy seguro de que los padres ya se ha definido) porque se ve más limpio, esp. cuando el anidamiento es muy profundo

Sin embargo, el primer método tiene algunas ventajas, uno aún no discutido es que un módulo anidado tiene acceso a cualquier constancia léxica disponible en el módulo adjunto.

2

Parece que la respuesta de la barandilla es también la razón de este comportamiento:

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] 

El módulo interno a es una constante dentro del módulo exterior A, y por lo tanto no es visible mediante el segundo método.

Edición de mi comentario anterior:

Esto se explica en 7.9 "búsqueda constante" de "The Ruby Programming Language" (primera edición). La parte relevante aquí es Module.nesting, que no contiene el módulo externo en el segundo ejemplo, por lo que A solo puede encontrarse en el ámbito global.

Cuestiones relacionadas