Nivel inicial5 min de lectura · Publicado el

Ejemplos de mixin en Ruby: include, extend y prepend

Mixins en Ruby: el módulo Numerable es una cuchilla que encaja en la clase Contador con include y en el objeto especial con extend. Mixins: compartir sin subclasesrubentejera.com ContadorincludeespecialextendNumerablela misma pieza
La cuchilla es el módulo Numerable: la misma pieza sirve en la clase Contador, con include, y en un solo objeto, especial, con extend. Se comparte sin crear subclases.

En Ruby una clase solo puede heredar de otra. Pero a veces quieres que clases muy distintas compartan un comportamiento, como saber escribirse con palabras o compararse entre sí. Para eso están los mixins: escribes los métodos en un módulo y los mezclas donde haga falta.

Es como un accesorio de un robot de cocina: la misma cuchilla de picar sirve en varios modelos, sin que tengas que comprar otro robot.

Estos son cuatro ejemplos, del más habitual al más específico.

1. include: mixin dentro de una clase

module Numerable
  NOMBRES = { 1 => "uno", 2 => "dos", 3 => "tres" }.freeze

  def to_s
    NOMBRES.fetch(@number, "muchos")
  end
end

class Contador
  include Numerable   # todos los objetos de Contador tienen to_s del módulo
  attr_accessor :number
end

contador = Contador.new
contador.number = 3
puts contador   # tres

otro = Contador.new
otro.number = 2
puts otro       # dos

puts llama a to_s por ti, así que no hace falta escribir puts "#{contador.to_s}".

Ruby busca los métodos en una lista ordenada, la cadena de ancestros. Con include, el módulo se coloca justo después de la clase:

Contador.ancestors.first(3)   # => [Contador, Numerable, Object]

2. extend: mixin en un solo objeto

class Marcador
  attr_accessor :number

  def to_s = @number.to_s
end

especial = Marcador.new
especial.extend(Numerable)   # solo este objeto recibe los métodos del módulo
especial.number = 3
puts especial                # tres

normal = Marcador.new
normal.number = 2
puts normal                  # 2

Fíjate en que Marcador ya tenía su propio to_s, y aun así especial usa el del módulo: extend coloca el módulo por delante de la clase, pero solo para ese objeto. El resto de objetos de Marcador no cambian.

Puedes verlo en la cadena de ancestros de ese objeto concreto (su «clase singleton», una clase oculta que solo tiene él):

especial.singleton_class.ancestors.first(3)
# => [#<Class:#<Marcador:0x...>>, Numerable, Marcador]

3. extend en la clase: métodos de clase

Si usas extend dentro de la clase, los métodos del módulo pasan a ser métodos de clase: se llaman sobre la clase, no sobre sus objetos.

module Saludo
  def saludar = "Hey"
end

class Persona
  extend Saludo   # extend en vez de include
end

Persona.saludar       # => "Hey"
Persona.new.saludar   # NoMethodError: los objetos no tienen el método

4. prepend: envolver un método de la clase

Con prepend, el módulo se coloca antes que la clase en la cadena de ancestros. Así puede cambiar un método de la clase y llamar al original con super:

module EnMayusculas
  def to_s = super.upcase
end

class Etiqueta
  prepend EnMayusculas

  def to_s = "hola"
end

puts Etiqueta.new                 # HOLA
Etiqueta.ancestors.first(3)       # => [EnMayusculas, Etiqueta, Object]

Resumen

Forma Dónde van los métodos Uso típico
include Modulo En los objetos de la clase Compartir comportamiento entre clases
objeto.extend(Modulo) Solo en ese objeto Darle algo especial a un objeto concreto
extend Modulo (dentro de la clase) En la propia clase Métodos de clase compartidos
prepend Modulo En los objetos, por delante de la clase Envolver o adornar métodos existentes
Cadena de ancestros según cómo se mezcla el módulo. Con include en Contador: Contador, Numerable y Object; el módulo va justo después de la clase. Con prepend en Etiqueta: EnMayusculas, Etiqueta y Object; el módulo va antes que la clase. Con extend solo en el objeto especial: su clase singleton, Numerable y Marcador; el módulo va por delante de la clase. Ruby busca el método de arriba abajo.
Ruby recorre cada columna de arriba abajo y usa el primer to_s que encuentra. Lo que cambia entre las tres formas es dónde queda el módulo, en ámbar, respecto a la clase.
Herencia para lo que algo es; mixins para lo que algo sabe hacer.

Para practicar, prueba el ejercicio práctico de módulos en Ruby. Y si trabajas con Rails, los concerns son mixins con algunas comodidades añadidas.

Fuentes

Comprobado en noviembre de 2026 en la documentación oficial de Ruby 4.0: Module (include, prepend, ancestors) y Object#extend.

Todos los ejemplos se han ejecutado en Docker con la imagen ruby:latest (Ruby 4.0.9). Respecto al original se ha cambiado el estilo del código al habitual en Ruby (nombres en snake_case, puts objeto en lugar de puts"#{objeto.to_s}") y se ha añadido el ejemplo de prepend.