Menu
Coddy logo textTech

Mixins simples

Parte de la sección Programación Orientada a Objetos del Journey de Lua de Coddy. Lección 51 de 70.

La composición te permite colocar objetos dentro de otros objetos. Pero ¿qué ocurre si quieres compartir comportamiento entre clases no relacionadas?

Un Player y un MenuItem podrían necesitar ambos un método :describe(), pero no comparten una clase principal. Aquí es donde entran en juego los mixins.

Un mixin es simplemente una tabla que contiene funciones. Puedes «mezclar» estas funciones en una clase copiándolas:

local Printable = {}

function Printable:describe()
    print("Object: " .. tostring(self))
end

function Printable:log(message)
    print("[LOG] " .. message)
end

Para aplicar este mixin a una clase, copias cada función de la tabla del mixin en la tabla de la clase:

local function applyMixin(class, mixin)
    for key, value in pairs(mixin) do
        class[key] = value
    end
end

local Player = {}
Player.__index = Player

applyMixin(Player, Printable)  -- Ahora Player tiene :describe() y :log()

Después de aplicar el mixin, cualquier instancia de Player puede llamar a esos métodos como si estuvieran definidos directamente en la clase:

local p = setmetatable({}, Player)
p:log("Player created")  -- [LOG] Player creado

A diferencia de la herencia, los mixins no crean una relación entre padre e hijo. Simplemente estás copiando funciones de una tabla a otra.

Esto hace que los mixins sean perfectos para compartir comportamientos utilitarios, como el registro, la serialización o los métodos de descripción, entre clases que, por lo demás, no tienen nada en común.

challenge icon

Desafío

Fácil

¡Construyamos un sistema de etiquetado usando mixins! Crearás un mixin Taggable que se puede aplicar a cualquier clase, lo que dará a los objetos la capacidad de gestionar una colección de etiquetas, útil para categorizar elementos, publicaciones o cualquier entidad que necesite etiquetas.

Organizarás tu código en tres archivos:

  • Taggable.lua: crea una tabla de mixin que contenga dos métodos:
    • :addTag(tag): añade una etiqueta a self.tags (se supone que la tabla existe)
    • :listTags(): muestra todas las etiquetas en el formato Tags: tag1, tag2, tag3 (o Tags: none si está vacía)
  • Article.lua: crea una clase Article con un constructor :new(title) que almacene el título e inicialice una tabla tags vacía. Aplica el mixin Taggable para proporcionar capacidades de etiquetado a las instancias de Article. Incluye un método :getTitle() que devuelva el título del artículo.
  • main.lua: escribe aquí la función auxiliar applyMixin (la usarás en Article.lua mediante require). Después, lee las entradas correspondientes al título de un artículo y a dos etiquetas. Crea un Article, añádele ambas etiquetas, muestra el título y enumera todas las etiquetas.

Recibirás tres entradas:

  1. El título del artículo (una cadena)
  2. La primera etiqueta que se añadirá (una cadena)
  3. La segunda etiqueta que se añadirá (una cadena)

Tu salida debe mostrar el título del artículo seguido de sus etiquetas:

Title: {title}
Tags: {tag1}, {tag2}

Por ejemplo, si las entradas son Lua Basics, programming y tutorial, la salida debe ser:

Title: Lua Basics
Tags: programming, tutorial

Recuerda: los métodos del mixin funcionan porque las instancias de Article tienen una tabla tags sobre la que pueden operar los métodos del mixin. El mixin no crea esta tabla. Tu constructor de Article sí lo hace. ¡El mixin solo proporciona el comportamiento compartido!

Pruébalo tú mismo

-- Archivo principal para el sistema de etiquetado
local Taggable = require('Taggable')
local Article = require('Article')

-- TODO: Implementa la función applyMixin
-- Esta función debería copiar todos los métodos de una tabla mixin a una tabla target
function applyMixin(target, mixin)
    -- TODO: Recorre el mixin y copia cada método a target
end

-- Lee las entradas
local title = io.read()
local tag1 = io.read()
local tag2 = io.read()

-- TODO: Crea un Article con el título dado

-- TODO: Añade ambas etiquetas al article

-- TODO: Imprime el título en el formato: Title: {title}

-- TODO: Lista todas las etiquetas usando el método listTags
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Lua online