Menu
Coddy logo textTech

Aplicación de múltiples Mixins

Parte de la sección Programación Orientada a Objetos del Journey de Lua de Coddy — lección 52 de 70.

Un solo mixin añade un conjunto de comportamientos a una clase. Pero los objetos reales a menudo necesitan capacidades de múltiples fuentes. Un objeto de juego podría necesitar moverse y ser visible en pantalla—dos preocupaciones separadas que no pertenecen al mismo mixin.

La solución es sencilla: aplica múltiples mixins a la misma clase. Cada mixin aporta sus propios métodos, y la clase termina teniendo todos ellos:

local Movable = {}
function Movable:move(dx, dy)
    self.x = self.x + dx
    self.y = self.y + dy
end

local Visible = {}
function Visible:show()
    print("Showing at " .. self.x .. ", " .. self.y)
end
function Visible:hide()
    print("Hidden")
end

Aplica ambos mixins a tu clase usando la misma función auxiliar de antes:

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

local GameObject = {}
GameObject.__index = GameObject

applyMixin(GameObject, Movable)
applyMixin(GameObject, Visible)

Ahora las instancias de GameObject pueden tanto moverse como mostrarse a sí mismas:

local obj = setmetatable({x = 0, y = 0}, GameObject)
obj:move(5, 3)
obj:show()  -- Mostrando en 5, 3

Una advertencia: si dos mixins definen el mismo nombre de método, el segundo aplicado sobrescribirá al primero. Mantén tus métodos de mixin distintos para evitar comportamientos inesperados.

challenge icon

Desafío

Fácil

¡Vamos a construir una clase Character para un juego que combina múltiples capacidades usando mixins! Tu personaje podrá tanto atacar enemigos como curarse a sí mismo—dos comportamientos distintos que provienen de mixins separados.

Organizarás tu código en cuatro archivos:

  • Attacker.lua: Crea un mixin con un método :attack(targetName) que imprima {self.name} attacks {targetName} for {self.damage} damage! (asume que el objeto tiene los campos name y damage)
  • Healer.lua: Crea un mixin con un método :heal(amount) que sume la cantidad a self.health e imprima {self.name} heals for {amount}. Health: {newHealth}
  • Character.lua: Crea una clase Character con un constructor :new(name, health, damage) que almacene los tres atributos. Aplica tanto el mixin Attacker como el Healer para que cada personaje pueda atacar y curar. Incluye un método :status() que imprima {name} - Health: {health}, Damage: {damage}
  • main.lua: Escribe la función auxiliar applyMixin aquí. Lee las entradas para el nombre de un personaje, salud, daño, un objetivo para atacar y una cantidad de curación. Crea un Character, muestra su estado, haz que ataque al objetivo, se cure a sí mismo y luego muestra su estado nuevamente.

Recibirás cinco entradas:

  1. Nombre del personaje (una cadena)
  2. Salud inicial (un número)
  3. Valor de daño (un número)
  4. Nombre del objetivo a atacar (una cadena)
  5. Cantidad a curar (un número)

Tu salida debe mostrar al personaje usando ambas habilidades del mixin:

{name} - Health: {health}, Damage: {damage}
{name} attacks {target} for {damage} damage!
{name} heals for {healAmount}. Health: {newHealth}
{name} - Health: {newHealth}, Damage: {damage}

Por ejemplo, si las entradas son Warrior, 100, 25, Goblin y 30, la salida debería ser:

Warrior - Health: 100, Damage: 25
Warrior attacks Goblin for 25 damage!
Warrior heals for 30. Health: 130
Warrior - Health: 130, Damage: 25

Cada mixin aporta su propio método a la clase Character. El personaje no hereda de ninguno de los mixins—simplemente adquiere sus habilidades a través de la función applyMixin. ¡Este es el poder de combinar múltiples mixins!

Pruébalo tú mismo

-- Archivo principal

-- TODO: Escribir la función auxiliar applyMixin
-- Esta función debe copiar todos los métodos de una tabla mixin a una tabla de destino
local function applyMixin(target, mixin)
    -- TODO: Implementar la aplicación del mixin
end

-- Hacer que applyMixin esté disponible globalmente para que Character.lua pueda usarlo
_G.applyMixin = applyMixin

local Character = require('Character')

-- Leer entradas
local name = io.read()
local health = tonumber(io.read())
local damage = tonumber(io.read())
local targetName = io.read()
local healAmount = tonumber(io.read())

-- TODO: Crear un Character con el nombre, salud y daño dados

-- TODO: Mostrar el estado del personaje

-- TODO: Hacer que el personaje ataque al objetivo

-- TODO: Hacer que el personaje se cure a sí mismo

-- TODO: Mostrar el estado del personaje de nuevo
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