Menu
Coddy logo textTech

Relación "Tiene-Un"

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

A lo largo de este curso, has usado la herencia para compartir comportamiento entre clases: un Dog «es un» Animal. Pero la herencia no siempre es la herramienta adecuada.

A veces, los objetos no comparten un árbol genealógico; en su lugar, un objeto simplemente contiene a otro. Esto se llama composición y modela una relación de «tiene un».

Considera un automóvil. Un automóvil no es un tipo de motor. tiene un motor. El motor es un objeto separado que existe dentro del automóvil:

local Engine = {}
Engine.__index = Engine

function Engine:new(horsepower)
    local obj = {horsepower = horsepower}
    setmetatable(obj, Engine)
    return obj
end

local Car = {}
Car.__index = Car

function Car:new(model, engine)
    local obj = {
        model = model,
        engine = engine  -- Almacena el objeto Engine dentro de Car
    }
    setmetatable(obj, Car)
    return obj
end

Al crear un coche, pasas un objeto de motor existente a su constructor:

local myEngine = Engine:new(200)
local myCar = Car:new("Sedan", myEngine)

print(myCar.engine.horsepower)  -- 200

El automóvil no hereda del motor. Simplemente mantiene una referencia a él. Esto mantiene ambas clases independientes. Podrías sustituirlo por un motor diferente o usar la misma clase de motor en una motocicleta.

La composición te ofrece una flexibilidad que la herencia no puede: ensamblas objetos a partir de partes en lugar de encasillarlos en una jerarquía familiar rígida.

challenge icon

Desafío

Fácil

¡Construyamos un sistema informático usando composición! En lugar de herencia, crearás una Computer que tiene una CPU dentro: demostrando la relación «tiene-un».

Organizarás tu código en tres archivos:

  • CPU.lua: Crea una clase CPU con un constructor :new(brand, speed) que almacene el nombre de la marca y la velocidad en GHz. Incluye un método :getInfo() que devuelva una cadena con el formato: {brand} @ {speed}GHz
  • Computer.lua: Crea una clase Computer cuyo constructor :new(model, cpu) acepte un nombre de modelo y un objeto CPU. Computer almacena el objeto CPU dentro de sí mismo (¡composición!). Incluye un método :describe() que muestre el modelo del ordenador y la información de su CPU.
  • main.lua: ¡Une todos los elementos! Lee las entradas correspondientes a la marca de la CPU, la velocidad de la CPU y el modelo del ordenador. Crea primero un objeto CPU y después pásalo al constructor de Computer. Por último, llama al método :describe() del ordenador.

Recibirás tres entradas:

  1. La marca de la CPU (una cadena)
  2. La velocidad de la CPU en GHz (un número)
  3. El nombre del modelo del ordenador (una cadena)

Tu salida debe mostrar la descripción del ordenador, que incluye información de su CPU contenida:

Model: {model}
CPU: {brand} @ {speed}GHz

Por ejemplo, si las entradas son Intel, 3.5 y WorkStation, la salida debe ser:

Model: WorkStation
CPU: Intel @ 3.5GHz

Observa que Computer no hereda de CPU. Simplemente mantiene una referencia a una. El método :describe() de Computer accede a los datos de la CPU a través del objeto almacenado, mostrando cómo la composición te permite construir objetos complejos a partir de partes más sencillas.

Pruébalo tú mismo

-- main.lua
-- Reúne todo usando composición

local CPU = require('CPU')
local Computer = require('Computer')

-- Leer entradas
local cpuBrand = io.read()
local cpuSpeed = tonumber(io.read())
local computerModel = io.read()

-- TODO: Crea un objeto CPU con la marca y la velocidad

-- TODO: Crea un objeto Computer con el modelo y el objeto CPU

-- TODO: Llama al método describe() de la computadora para imprimir la salida
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