Menu
Coddy logo textTech

Delegación

Parte de la sección Object Oriented Programming del Journey de Lua de Coddy — lección 50 de 70.

Almacenar un objeto dentro de otro objeto es solo el primer paso. El verdadero poder de la composición proviene de la delegación: cuando el objeto externo reenvía las llamadas a métodos a sus componentes internos.

Piense en arrancar un coche. No mete la mano bajo el capó y hace girar el motor manualmente. En su lugar, gira la llave y el coche se encarga del resto internamente.

En el código, esto significa que la clase Car proporciona un método :start() simple que delega el trabajo real al motor:

function Car:start()
    print("Turning the key...")
    self.engine:run()  -- Delegar al objeto interno
end

El coche no necesita saber cómo funciona el motor; simplemente le dice al motor que haga su trabajo. Esto mantiene las responsabilidades separadas. La clase Engine maneja la lógica del motor, mientras que Car coordina las piezas:

function Engine:run()
    print("Engine running at " .. self.horsepower .. " HP")
end

local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- Salida:
-- Girando la llave...
-- Motor funcionando a 250 HP

La delegación crea una interfaz limpia para los usuarios de su clase. Interactúan con el coche, no con sus partes internas. Si más adelante cambia a una implementación de motor diferente, la interfaz pública del coche permanece igual; solo cambia la delegación interna.

challenge icon

Desafío

Fácil

¡Vamos a construir un sistema de reproductor de música que demuestre la delegación! Crearás un componente Speaker y un MusicPlayer que lo contenga. El reproductor no gestionará la salida de sonido directamente; en su lugar, delegará esa responsabilidad a su altavoz interno.

Organizarás tu código en tres archivos:

  • Speaker.lua: Crea una clase Speaker con un constructor :new(volume) que almacene el nivel de volumen. Incluye un método :playSound(trackName) que imprima: Playing "{trackName}" at volume {volume}
  • MusicPlayer.lua: Crea una clase MusicPlayer cuyo constructor :new(brand, speaker) acepte un nombre de marca y un objeto Speaker. El reproductor almacena el altavoz en su interior. Incluye estos métodos:
    • :play(trackName) — imprime {brand} player starting... y luego delega al método :playSound() del altavoz
    • :stop() — imprime {brand} player stopped
  • main.lua: ¡Une todo! Lee las entradas para el volumen del altavoz, la marca del reproductor y un nombre de pista. Crea primero un Speaker, luego pásalo al constructor de MusicPlayer. Llama al método :play() del reproductor con el nombre de la pista, luego llama a :stop().

Recibirás tres entradas:

  1. El volumen del altavoz (un número)
  2. La marca del reproductor de música (una cadena)
  3. El nombre de la pista a reproducir (una cadena)

Tu salida debería mostrar al reproductor coordinándose con su altavoz:

{brand} player starting...
Playing "{trackName}" at volume {volume}
{brand} player stopped

Por ejemplo, si las entradas son 75, SoundMax, y Summer Vibes, la salida debería ser:

SoundMax player starting...
Playing "Summer Vibes" at volume 75
SoundMax player stopped

Observa cómo el MusicPlayer no sabe cómo producir sonido; simplemente le dice a su altavoz que se encargue de esa parte. ¡Esto es la delegación en acción: el objeto externo proporciona una interfaz limpia mientras que el componente interno realiza el trabajo especializado!

Hoja de referencia

La delegación permite que un objeto externo reenvíe llamadas a métodos a sus componentes internos, manteniendo las responsabilidades separadas y creando interfaces limpias.

El objeto externo proporciona métodos simples que delegan el trabajo a los objetos internos:

function Car:start()
    print("Turning the key...")
    self.engine:run()  -- Delegate to the inner object
end

El objeto interno maneja su propia lógica especializada:

function Engine:run()
    print("Engine running at " .. self.horsepower .. " HP")
end

local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- Output:
-- Turning the key...
-- Engine running at 250 HP

Beneficios de la delegación:

  • La clase externa no necesita saber cómo funciona el objeto interno
  • Los usuarios interactúan con una interfaz pública limpia
  • Las implementaciones internas se pueden intercambiar sin cambiar la interfaz pública

Pruébalo tú mismo

-- main.lua
-- ¡Juntando todo!

local Speaker = require('Speaker')
local MusicPlayer = require('MusicPlayer')

-- Leer entradas
local volume = tonumber(io.read())
local brand = io.read()
local trackName = io.read()

-- TODO: Crear un Speaker con el volumen dado

-- TODO: Crear un MusicPlayer con la marca y el altavoz

-- TODO: Llamar al método play del reproductor con el nombre de la pista

-- TODO: Llamar al método stop del reproductor
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 Object Oriented Programming