Menu
Coddy logo textTech

Delegação

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

Armazenar um objeto dentro de outro objeto é apenas o primeiro passo. O verdadeiro poder da composição vem da delegação, quando o objeto externo encaminha chamadas de método para seus componentes internos.

Pense em dar partida em um carro. Você não coloca a mão sob o capô e gira o motor manualmente. Em vez disso, você vira a chave, e o carro cuida do resto internamente.

No código, isso significa que a classe Car fornece um método simples :start() que delega o trabalho efetivo ao motor:

function Car:start()
    print("Turning the key...")
    self.engine:run()  -- Delega para o objeto interno
end

O carro não precisa saber como o motor funciona. Ele apenas diz ao motor para fazer seu trabalho. Isso mantém as responsabilidades separadas. A classe Engine lida com a lógica do motor, enquanto Car coordena as partes:

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

local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- Saída:
-- Girando a chave...
-- Motor rodando a 250 HP

A delegação cria uma interface limpa para os usuários da sua classe. Eles interagem com o carro, não com suas partes internas. Se mais tarde você substituir a implementação do motor por outra, a interface pública do carro permanecerá a mesma: somente a delegação interna será alterada.

challenge icon

Desafio

Fácil

Vamos criar um sistema de reprodução de música que demonstra delegação! Você criará um componente Speaker e um MusicPlayer que o contém. O player não lidará diretamente com a saída de som; em vez disso, delegará essa responsabilidade ao seu speaker interno.

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

  • Speaker.lua: crie uma classe Speaker com um construtor :new(volume) que armazene o nível de volume. Inclua um método :playSound(trackName) que imprima: Playing "{trackName}" at volume {volume}
  • MusicPlayer.lua: crie uma classe MusicPlayer cujo construtor :new(brand, speaker) aceite o nome de uma marca e um objeto Speaker. O player armazena o speaker dentro de si. Inclua estes métodos:
    • :play(trackName): imprime {brand} player starting... e então delega ao método :playSound() do speaker
    • :stop(): imprime {brand} player stopped
  • main.lua: reúna tudo! Leia as entradas referentes ao volume do speaker, à marca do player e ao nome de uma faixa. Crie primeiro um Speaker e, em seguida, passe-o ao construtor de MusicPlayer. Chame o método :play() do player com o nome da faixa e, depois, chame :stop().

Você receberá três entradas:

  1. O volume do speaker (um número)
  2. A marca do player de música (uma string)
  3. O nome da faixa a ser reproduzida (uma string)

Sua saída deve mostrar o player coordenando-se com seu speaker:

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

Por exemplo, se as entradas forem 75, SoundMax e Summer Vibes, a saída deverá ser:

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

Observe como o MusicPlayer não sabe como produzir som. Ele simplesmente diz ao seu speaker para cuidar dessa parte. Isso é delegação em ação: o objeto externo fornece uma interface limpa, enquanto o componente interno realiza o trabalho especializado!

Experimente você mesmo

-- main.lua
-- Junte tudo!

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

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

-- TODO: Crie um Speaker com o volume fornecido

-- TODO: Crie um MusicPlayer com a marca e o speaker

-- TODO: Chame o método play do player com o nome da faixa

-- TODO: Chame o método stop do player
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