Estoy bastante familiarizado con cuándo usar subclases y módulos, pero más recientemente he estado viendo clases anidadas como esta:
class Foo
class Bar
# do some useful things
end
end
Además de clases anidadas en módulos de esta manera:
module Baz
class Quux
# more code
end
end
O bien la documentación y los artículos son escasos o no estoy bien informado sobre el tema para buscar los términos de búsqueda correctos, pero parece que no puedo encontrar mucha información sobre el tema.
¿Podría alguien proporcionar ejemplos o enlaces a publicaciones sobre por qué / cuándo se utilizarían esas técnicas?

Car.newyCar::Wheel.new. Definitivamente no necesita inicializar unCarobjeto para inicializar unCar::Wheelobjeto en Ruby, pero laCarclase debe cargarse y ejecutarse paraCar::Wheelque se pueda usar.CaryCar::Wheel. Los módulos (y, por lo tanto, las clases) son simplemente espacios de nombres para constantes, no existe una clase anidada o un módulo anidado en Ruby.Car::Wheel.new. Auge. Acabo de construir unWheelobjeto que no está anidado dentro de unCarobjeto.En Ruby, definir una clase anidada es similar a definir una clase en un módulo. En realidad, no fuerza una asociación entre las clases, solo crea un espacio de nombres para las constantes. (Los nombres de clase y módulo son constantes).
La respuesta aceptada no era correcta sobre nada. 1 En el ejemplo a continuación, creo una instancia de la clase encerrada léxicamente sin que exista una instancia de la clase encerradora.
Las ventajas son las mismas que para los módulos: encapsulación, agrupación de código utilizado en un solo lugar y colocación de código más cerca de donde se utiliza. Un proyecto grande puede tener un módulo externo que ocurre una y otra vez en cada archivo fuente y contiene muchas definiciones de clase. Cuando los diversos marcos y códigos de biblioteca hacen esto, solo contribuyen con un nombre al nivel superior, lo que reduce la posibilidad de conflictos. Prosaico, sin duda, pero es por eso que se usan.
El uso de una clase en lugar de un módulo para definir el espacio de nombres externo puede tener sentido en un programa o script de un archivo, o si ya usa la clase de nivel superior para algo, o si realmente va a agregar código para vincular las clases juntas en verdadera clase interna estilo de . Ruby no tiene clases internas, pero nada le impide crear el mismo comportamiento en el código. Hacer referencia a los objetos externos de los internos aún requerirá puntear desde la instancia del objeto externo, pero anidar las clases sugerirá que esto es lo que podría estar haciendo. Un programa cuidadosamente modularizado siempre puede crear primero las clases que lo encierran, y razonablemente se pueden descomponer con clases anidadas o internas. No puedes llamar
newa un módulo.Puede usar el patrón general incluso para scripts, donde el espacio de nombres no es muy necesario, solo por diversión y práctica ...
fuente
Bestá dentro de la clase . La constante tiene un espacio de nombres dentro de la clase , pero no hay absolutamente ninguna relación entre el objeto al que hace referencia (que en este caso es una clase) y la clase a la que hace referencia .ABABAYou can't call new on a module.así que, en términos básicos, si solo quiero crear espacios de nombres para algunas clases y nunca necesito crear una instancia de la "clase" externa, entonces Yo usaría un módulo externo. Pero si quiero crear una instancia de la "clase" envolvente / externa, la convertiría en una Clase en lugar de un Módulo. Al menos esto tiene sentido para mí.Probablemente quiera usar esto para agrupar sus clases en un módulo. Una especie de espacio de nombres.
por ejemplo, la gema de Twitter usa espacios de nombres para lograr esto:
Entonces, ambos
Clienty lasSearchclases viven bajo elTwittermódulo.Si desea verificar las fuentes, el código para ambas clases se puede encontrar aquí y aquí .
¡Espero que esto ayude!
fuente
Hay otra diferencia entre las clases anidadas y los módulos anidados en Ruby antes de 2.5 que otras respuestas no pudieron cubrir y creo que deben mencionarse aquí. Es el proceso de búsqueda.
En resumen: debido a la búsqueda constante de nivel superior en Ruby antes de 2.5, Ruby puede terminar buscando su clase anidada en el lugar incorrecto (
Objecten particular) si usa clases anidadas.En Ruby anterior a 2.5:
Estructura de clase anidada: suponga que tiene una clase
X, con clase anidadaY, oX::Y. Y luego tienes una clase de nivel superior llamada tambiénY. SiX::Yno está cargado, entonces ocurre lo siguiente cuando se llamaX::Y:Al no haber encontrado
YenX, Ruby va a tratar de mirar hacia arriba en los antepasados deX. Ya queXes una clase y no un módulo, tiene ancestros, entre los cuales se encuentran[Object, Kernel, BasicObject]. Entonces, trata de buscarYadentroObject, donde lo encuentra con éxito.Sin embargo, es el nivel superior
Yy noX::Y. Recibirá esta advertencia:Estructura de módulo anidado: suponga que en el ejemplo anterior
Xes un módulo y no una clase.Un módulo solo se tiene a sí mismo como ancestro:
X.ancestorsproduciría[X].En este caso, Ruby no podrá buscar a
Yuno de sus antepasadosXy lanzará unNameError. Los rieles (o cualquier otro marco con carga automática) intentarán cargarseX::Ydespués de eso.Consulte este artículo para obtener más información: https://blog.jetbrains.com/ruby/2017/03/why-you-should-not-use-a-class-as-a-namespace-in-rails-applications/
In Ruby 2.5: Se
eliminó la búsqueda constante de nivel superior.
Puede usar clases anidadas sin temor a encontrar este error.
fuente
Además de las respuestas anteriores: Módulo en Ruby es una clase
fuente
new. Entonces, aunque puede decir que los módulos son una clase (minúsculas), no son lo mismo que una clase (mayúsculas) :)