Menu
Coddy logo textTech

Relacionamento Tem-Um

Parte da seção Programação Orientada a Objetos do Journey de Lua da Coddy. Lição 49 de 70.

Ao longo deste curso, você usou herança para compartilhar comportamentos entre classes: um Dog "é um" Animal. Mas a herança nem sempre é a ferramenta certa.

Às vezes, os objetos não compartilham uma árvore genealógica; em vez disso, um objeto simplesmente contém outro. Isso é chamado de composição e modela uma relação de "tem-um".

Considere um carro. Um carro não é um tipo de motor. Ele tem um motor. O motor é um objeto separado que existe dentro do carro:

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  -- Armazena o objeto Engine dentro de Car
    }
    setmetatable(obj, Car)
    return obj
end

Ao criar um carro, você passa um objeto de motor existente para seu construtor:

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

print(myCar.engine.horsepower)  -- 200

O carro não herda do motor. Ele simplesmente mantém uma referência a ele. Isso mantém ambas as classes independentes. Você poderia substituir por um motor diferente ou usar a mesma classe de motor em uma motocicleta.

A composição oferece uma flexibilidade que a herança não oferece: você monta objetos a partir de partes em vez de prendê-los a uma hierarquia familiar rígida.

challenge icon

Desafio

Fácil

Vamos construir um sistema de computador usando composição! Em vez de herança, você criará um Computer que tem uma CPU dentro dele: demonstrando a relação "tem-um".

Você organizará seu código em três arquivos:

  • CPU.lua: Crie uma classe CPU com um construtor :new(brand, speed) que armazena o nome da marca e a velocidade em GHz. Inclua um método :getInfo() que retorna uma string no formato: {brand} @ {speed}GHz
  • Computer.lua: Crie uma classe Computer cujo construtor :new(model, cpu) aceita um nome de modelo e um objeto CPU. O Computer armazena o objeto CPU dentro de si (composição!). Inclua um método :describe() que exibe o modelo do computador e as informações de sua CPU.
  • main.lua: Reúna tudo! Leia as entradas referentes à marca da CPU, à velocidade da CPU e ao modelo do computador. Crie primeiro um objeto CPU e, em seguida, passe-o ao construtor do Computer. Por fim, chame o método :describe() do computador.

Você receberá três entradas:

  1. A marca da CPU (uma string)
  2. A velocidade da CPU em GHz (um número)
  3. O nome do modelo do computador (uma string)

Sua saída deve mostrar a descrição do computador, que inclui informações de sua CPU contida:

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

Por exemplo, se as entradas forem Intel, 3.5 e WorkStation, a saída deverá ser:

Model: WorkStation
CPU: Intel @ 3.5GHz

Observe como o Computer não herda de CPU. Ele simplesmente mantém uma referência a uma delas. O método :describe() do Computer acessa os dados da CPU por meio do objeto armazenado, mostrando como a composição permite construir objetos complexos a partir de partes mais simples!

Experimente você mesmo

-- main.lua
-- Junte tudo usando composição

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

-- Lê as entradas
local cpuBrand = io.read()
local cpuSpeed = tonumber(io.read())
local computerModel = io.read()

-- TODO: Crie um objeto CPU com a marca e a velocidade

-- TODO: Crie um objeto Computer com o modelo e o objeto CPU

-- TODO: Chame o método describe() do computador para imprimir a saída
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de Lua online