Bienvenidos una vez más a Ruby desde Cero. En los últimos capítulos estudiamos las clases y el paradigma orientado a objetos aplicados al lenguaje. Si aún no te has puesto al día con la serie te invito a echarle un vistazo a Ruby desde Cero
En este nuevo capítulo estaremos estudiando los módulos en Ruby, al igual que en los capítulos anteriores definiendo cada una de las características, mostrando la sintaxis y ejecutando ejemplos básicos para comprender mejor el tema.
¿Qué son los módulos?
Un módulo es una colección de métodos y constantes. Mediante el uso de módulos, podemos dividir el sistema o el programa en partes independientes para facilitarnos el uso de los métodos para reutilizarlos, es decir, los módulos podrían ser paquetes de métodos y clases relacionados que nos facilitarán encontrarlos más rápido.
Aunque el concepto de módulos se asemeja bastante al de clases que también tiene métodos, clases y constantes, se diferencian básicamente en que no se pueden crear objetos de un módulo, es decir, no se instancian los módulos.
Otra ventaja, es que podemos almacenar nuestros programas de forma modular: cada módulo añade una característica. Esto también lo permitían las clases, pero la ventaja de los módulos, es que no hace falta crear una serie de jerarquías, que podría llegar a ser engorroso.
Lo primero que debemos hacer para adentrarnos en el concepto y comenzar a elaborar algunos ejemplos es conocer la sintaxis:
module Identificador declaracion1 declaracion2 . . . end
Al igual que con los métodos de clase, se llama a un método del módulo precediendo su nombre con el nombre módulo y un punto ( . ), y se hace referencia a una constante utilizando el nombre del módulo y el signo de dos puntos ( : ).
Principales usos de los módulos
Los módulos en Ruby básicamente se utilizan para definir espacios de nombres (‘namespace’) que básicamente nos agrupa todas las clases, métodos, variables y otros elementos, dentro de un especie de grupo o paquete. Otro de los usos es el ‘mixins’ que nos permite agregar funcionalidad extras a una clase. Ésto lo definiremos mejor a continuación:
Espacios de nombres (‘namespace’)
Cuando estamos desarrollando algún proyecto grande y las lineas de código crecen desenfrenadamente, surge la necesidad de organizar de alguna forma nuestro código para poder manipularlo con facilidad, y es aquí donde nos es útil este tipo de implementación de los módulos.
Con los módulos es posible agrupar una serie de métodos y clases relacionadas de alguna manera en un archivo independiente, de tal manera que podamos utilizar estos métodos como una librería independiente. Un caso típico de un módulo es ‘Math’: este módulo cuenta con una serie de funciones trigonométricas agrupadas en un sólo paquete.
Los espacios de nombres también evitan el problema de que surja una ambiegüedad en el caso de que haya dos componentes con un mismo nombre. Por ejemplo, podemos tener dentro de un programa varias clases con el nombre “Settings”, pero cada una estará referida a algo concreto. Incluyendo esas clases en distintos módulos, conseguimos que puedan ser identificadas de forma unívoca.
Luego de tanta descripción veamos un ejemplo y así seguramente entenderemos mejor el concepto de namespace:
module Semana PRIMER_DIA = "lunes" def Semana.semanas_en_mes puts "un mes tiene cuatro semanas" return 4 end def Semana.semanas_en_anio puts "un anio tiene 52 semanas" end end class Codehero N_MESES = 10 def n_de_meses puts "las semanas inician el #{Semana::PRIMER_DIA}" number=10 * Semana::semanas_en_mes puts "cantidad de semanas en 10 meses es #{number}" end end puts Semana::PRIMER_DIA Semana.semanas_en_mes Semana.semanas_en_anio puts "===================" d1=Codehero.new d1.n_de_meses
En este ejemplo creamos un módulo ‘Semana’ que agrupa una serie de métodos y constantes relacionadas a una semana, que posteriormente utilizamos en una clase de prueba y fuera de ella. El resultado de esta ejecución lo podemos observar a continuación:
lunes un mes tiene cuatro semanas un anio tiene 52 semanas =================== las semanas inician el lunes un mes tiene cuatro semanas cantidad de semanas en 10 meses es 40
Mixins
Esta implementación de los módulos nos da una forma bastante elegante de agregarle funcionalidad a las clases. Sin embargo, su verdadero poder viene cuando el código en el mixin comienza a interactuar con el código de la clase que lo utiliza.
Vamos a ver un ejemplo en el que añadimos un método a la clase String que elimina los espacios en blanco de principio y fin de una cadena de caracteres.
module UtilidadesString def quitar_espacios self.to_s.strip.gsub(' ', '') end end class String include UtilidadesString end puts " Hola CodeHero, El Mejor Portal De Aprendizaje En Espaniol ".quitar_espacios
El resultado de la ejecución del programa es una cadena sin espacios:
HolaCodeHero,ElMejorPortalDeAprendizajeEnEspaniol
En el ejemplo vimos como le agregamos un método de instancia a la clase String, con esta herramienta también es posible extender una clase con métodos de clases, haciendo uso del ‘extend’. Haciendo posible incluir varios módulos en una misma clase, consiguiendo un efecto similar a una herencia múltiple no permitida por Ruby. Veamos un ejemplo sencillo de esto:
module Calendario def self.included(base) base.send :include, Dia base.send :extend, Semana end module Dia def dia_en_anio "un anio tiene 365 dias" end end module Semana PRIMER_DIA = "lunes" def semanas_x_mes(number) "#{number} meses tiene #{number * 4} semanas" end end end class MiClase include Calendario end #llamada a las clases puts MiClase.semanas_x_mes(4) puts MiClase.new.dia_en_anio
Como podemos ver en el ejemplo al agregar en un módulo el método ‘included’, éste se ejecutará cada vez que sea incluido por otro módulo o clase. En este ejemplo, cuando se incluye el módulo, añadimos los métodos de instancia(include) y de clase(extend). Dándonos como resultado una clase con comportamientos diferentes de dos módulos, el resultado de ejecutar el programa es el siguiente:
4 meses tiene 16 semanas un anio tiene 365 dias
Conclusión
En este capítulo aprendimos un concepto básico de Ruby como lo son los módulos, abarcando el concepto principal, ventajas, sintaxis, usos y manipulación de esta útil característica del lenguaje.
Si te surgen dudas con nuestros cursos, no te detengas y danos tus comentarios, que con gusto estamos dispuestos a resolver tus inquietudes.
¡Hasta el próximo capítulo!