Menu
CoddyTech

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é pasa si quieres compartir comportamiento entre clases no relacionadas?

Tanto Player como MenuItem podrían necesitar 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. «Mezclas» 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 esta mezcla a una clase, copia cada función de la tabla de la mezcla 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 padre-hijo. Simplemente estás copiando funciones de una tabla a otra.

Esto hace que los mixins sean perfectos para compartir comportamientos de utilidad, como métodos de registro, serialización o descripción, entre clases que, de otro modo, no tendrían nada en común.

challenge icon

Desafío

Fácil

¡Vamos a crear un sistema de etiquetas usando mixins! Crearás un mixin Taggable que se puede aplicar a cualquier clase y que permite que los objetos administren 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 mixin que contenga dos métodos:
    • :addTag(tag): agrega una etiqueta a self.tags (se supone que la tabla existe)
    • :listTags(): imprime 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. Incluye un método :getTitle() que devuelva el título del artículo.
  • main.lua: Escribe aquí la función auxiliar applyMixin y luego aplica el mixin con applyMixin(Article, Taggable) para dar capacidades de etiquetado a las instancias de Article. Después, lee los datos de entrada para el título de un artículo y dos etiquetas. Crea un Article, agrégale ambas etiquetas, imprime el título y enumera todas las etiquetas.

Recibirás tres datos de entrada:

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

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

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

Por ejemplo, si los datos de entrada son Lua Basics, programming y tutorial, la salida debería ser:

Title: Lua Basics
Tags: programming, tutorial

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

Pruébalo tú mismo

-- Archivo principal del sistema de etiquetas
local Taggable = require('Taggable')
local Article = require('Article')

-- TODO: Implementar la función applyMixin
-- Esta función debe copiar todos los métodos de una tabla mixin a una tabla de destino
function applyMixin(target, mixin)
    -- TODO: Recorrer mixin y copiar cada método a target
end

-- TODO: Aplicar el mixin Taggable a Article usando applyMixin

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

-- TODO: Crear un Article con el título proporcionado

-- TODO: Añadir ambas etiquetas al artículo

-- TODO: Imprimir el título con el formato: Title: {title}

-- TODO: Enumerar 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