En Ruby, módulos y clases son instancias de las clases Module
y Class
, respectivamente. Derivan sus nombres de la constante a la que están asignados. Cuando se escribe:
class A::B
# ...
end
Estás escribiendo con eficacia:
A::B ||= Class.new do
# ...
end
Cuál es la sintaxis de asignación constante válida, y asume que la constante A
ha sido inicializado correctamente y que se refiere a una Module
o Class
.
Por ejemplo, considere cómo las clases se definen generalmente:
class A
# ...
end
Lo que está pasando con eficacia es la siguiente:
Object::A ||= Class.new do
# ...
end
Ahora, cuando escribe:
class A
class B
# ...
end
end
Lo que en realidad El resultado se ve así:
(Object::A ||= Class.new).class_eval do
(A::B ||= Class.new).class_eval do
# ...
end
end
Esto es lo que está pasando, en orden:
- Una nueva instancia se
Class
asssigned a la A
constante de Object
, a menos que ya se ha inicializado.
- Se asigna una nueva instancia de
Class
a la constante B
de A
, a menos que ya se haya inicializado.
Esto asegura la existencia de todos clases exteriores antes de intentar definir cualquier clases internas.
También hay un cambio en el alcance, que le permite acceder directamente a las constantes de A
. Compare:
class A
MESSAGE = "I'm here!"
end
# Scope of Object
class A::B
# Scope of B
puts MESSAGE # NameError: uninitialized constant A::B::MESSAGE
end
# Scope of Object
class A
# Scope of A
class B
# Scope of B
puts MESSAGE # I'm here!
end
end
Según this blog post, el equipo central de Rubí llama a la "clase actual" la cref
. Desafortunadamente, el autor no detalla, pero como señala, está separado del contexto de self
.
As explained here, el cref
es una lista vinculado que representa el anidamiento de módulos en un cierto punto en el tiempo.
La corriente cref
se utiliza para constante y clase de búsqueda variable y para def
, undef
y alias
.
Como los otros han dicho, son diferentes maneras de expresar la misma cosa.
Hay, sin embargo, una diferencia sutil. Cuando escribe class A::B
, asume que la clase A
ya se ha definido. Si no lo ha hecho, obtendrá un NameError
y B
no se definirá en absoluto.
escritura módulos correctamente anidados:
class A
class B
end
end
Asegura la clase A
existe antes de intentar definir B
.
He actualizado la pregunta para mostrar que estos 2 enfoques no son lo mismo. – nickh
@nickh, no necesita editar la pregunta para incluir las respuestas. Debería [respaldar las respuestas que fueron útiles y aceptar la que definitivamente respondió su pregunta] (http://stackoverflow.com/faq#howtoask). –
El caso es que ninguno de ellos respondió la pregunta. Todas las respuestas dicen que los 2 enfoques son los mismos, que no lo son. – nickh