Módulos en Ruby

¿Qué son Módulos en Ruby?

Los módulos son similares a las clases en que contienen una colección de métodos, constantes y otros módulos y definiciones.

Pero a diferencia de las clases, no se pueden crear clases derivadas de los módulos.

Definición de Módulo

Un modulo es una clase no instanciable.

En Ruby, no hay interfaces, no hay herencia multiple, en su lugar hay modulos.

Un modulo puede definir metodos y variables de instancia y de clase

 

¿Que es un mixin?

Es una mezcla entre una clase y un modulo.

Hay dos formas de crear un mixin mientras se define una clase:

  • Mediante el método «include»: La clase adquiere toda la parte instanciable.
module ModuleExample
  def to_s
    return "uno" if @value == 1
    return "dos" if @value == 2
    return "tres" if @value == 3
    return "mucho"
  end
end


class ClassExample
  include ModuleExample
  attr_accessor :value
end


objectExample = ClassExample.new
objectExample.value = 3
print "#{objectExample.to_s}\n"     #tres

 

Modulo Comparable

class Tramo
  include Comparable

  attr :distancia
  
  def initialize (nombre, distancia)
    @nombre = nombre
    @distancia = distancia
  end

  def <=>(otro_tramo)
    self.distancia <=> otro_tramo.distancia

  end
end

tramo1 = Tramo.new("Tramo 1",1000)
tramo2 = Tramo.new("Tramo 2",2000)

puts tramo1 <=> tramo2  #-1
puts tramo1 < tramo2    #true
puts tramo1 == tramo2   #false
puts tramo1 > tramo2    #false

 

 

 

  • Mediante el método extend: El objeto adquiere todo el modulo, pero la clase en no.
module ModuleExample
  def to_s
    return "uno" if @value == 1
    return "dos" if @value == 2
    return "tres" if @value == 3
    return "mucho"
  end
end


class ClassExample
  attr_accessor :value
  def to_s
    @value.to_s
  end
end


objectExample = ClassExample.new
objectExample.value = 3
print "#{objectExample.to_s}\n"      #3

objectExample2 = ClassExample.new
objectExample2.value = 2
print "#{objectExample2.to_s}\n"      #2


objectExample.extend(ModuleExample)
print "#{objectExample.to_s}\n"      #tres

print "#{objectExample2.to_s}\n"      #2

Utilidades de los Módulos

1.- Actúan como librería, definiendo métodos cuyos nombres no interfieran con otros definidos en otros sitios.

Agrupan métodos similares bajo un nombre familiar. (namespace ó espacio de nombre)

 

2.- Permiten aumentar las funcionalidades de las clases: si una clase usa un módulo, los métodos de este módulo estarán disponibles en los objetos que procedan de esta clase.

Diferencia entre Módulos y Clases

Módulos Clases
Instancias No pueden generar instancias. Pueden generar instancias (objetos) y cada instancia tiene un estado (las variables de instancia).
Mezcla

Se pueden mezclar en las clases y otros módulos.

Los métodos y constantes del módulo que se mezcla se añaden a la clase, aumentando su funcionalidad

No se pueden mezclar con nada.
Herencia Un módulo no puede heredar.  Una clase puede heredar de otra pero no de un módulo.

 

 

La principal diferencia entre heredar de una clase y usar un módulo, es que puedes usar más de un módulo al mismo tiempo. Recordar, que no se permitía tener más de una clase madre. Esto permite añadir numerosas funciones al código.

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.

El código de Rails hace un fuerte uso de los módulos, en particular, la técnica de reabrir las definiciones de clases y módulos.

¿Cuando incluir un modulo o extender de una clase?

Para saber cuándo incluir un módulo o extender de una clase te puedes hacer la siguiente pregunta:

¿La ClaseHija especializa a la ClasePadre?

o mejor:

¿ClaseHija es un ClasePadre?

Si: Entonces es mejor crear una relación de herencia (extender una clase).

No: Es mejor utilizar un módulo.

 

Por ejemplo, supongamos que necesitamos definir la relación entre un Bus y un Auto. ¿Bus es un Auto? La respuesta es si y por lo tanto esta es una relación de herencia, Bus extiende Auto.

¿Radio es un Bus? La respuesta es no. Ser una radio no es una especialización de un bus. Por lo tanto, es mejor utilizar un módulo.

 

 

¿Se pueden hacer subclases de módulos?

No, Sin embargo se puede incluir el módulo en una clase u otro módulo para simular una herencia múltiple (utilidad mixin )

Esto no crea una subclase (que requeriría herencia) pero genera una relación is_a? entre la clase y el módulo.