Delegação
Parte da seção Object Oriented Programming 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 ligar um carro. Você não coloca a mão sob o capô e gira o motor manualmente. Em vez disso, você gira a chave e o carro cuida do resto internamente.
No código, isso significa que a classe Car fornece um método :start() simples que delega o trabalho real para o motor:
function Car:start()
print("Turning the key...")
self.engine:run() -- Delegar para o objeto interno
endO carro não precisa saber como o motor funciona—ele apenas diz ao motor para fazer o seu trabalho. Isso mantém as responsabilidades separadas. A classe Engine lida com a lógica do motor, enquanto a Car coordena as peças:
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 funcionando a 250 HPA 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 você posteriormente trocar por uma implementação de motor diferente, a interface pública do carro permanece a mesma — apenas a delegação interna muda.
Desafio
FácilVamos construir um sistema de tocador de música que demonstra a delegação! Você criará um componente Speaker e um MusicPlayer que o contém. O player não lidará com a saída de som diretamente — em vez disso, ele delegará essa responsabilidade ao seu alto-falante interno.
Você organizará seu código em três arquivos:
Speaker.lua: Crie uma classe Speaker com um construtor:new(volume)que armazena o nível do volume. Inclua um método:playSound(trackName)que imprime:Playing "{trackName}" at volume {volume}MusicPlayer.lua: Crie uma classe MusicPlayer cujo construtor:new(brand, speaker)aceita um nome de marca e um objeto Speaker. O player armazena o alto-falante dentro de si. Inclua estes métodos::play(trackName)— imprime{brand} player starting...e então delega para o método:playSound()do alto-falante:stop()— imprime{brand} player stopped
main.lua: Reúna tudo! Leia as entradas para o volume do alto-falante, a marca do player e o nome da faixa. Crie um Speaker primeiro, depois passe-o para o construtor do MusicPlayer. Chame o método:play()do player com o nome da faixa e, em seguida, chame:stop().
Você receberá três entradas:
- O volume do alto-falante (um número)
- A marca do tocador de música (uma string)
- O nome da faixa para tocar (uma string)
Sua saída deve mostrar o player coordenando com seu alto-falante:
{brand} player starting...
Playing "{trackName}" at volume {volume}
{brand} player stoppedPor exemplo, se as entradas forem 75, SoundMax, e Summer Vibes, a saída deve ser:
SoundMax player starting...
Playing "Summer Vibes" at volume 75
SoundMax player stoppedObserve como o MusicPlayer não sabe como produzir som — ele simplesmente diz ao seu alto-falante para cuidar dessa parte. Isso é a delegação em ação: o objeto externo fornece uma interface limpa enquanto o componente interno faz o trabalho especializado!
Folha de consulta
A delegação permite que um objeto externo encaminhe chamadas de método para seus componentes internos, mantendo as responsabilidades separadas e criando interfaces limpas.
O objeto externo fornece métodos simples que delegam o trabalho para objetos internos:
function Car:start()
print("Turning the key...")
self.engine:run() -- Delegate to the inner object
endO objeto interno lida com sua própria 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 HPBenefícios da delegação:
- A classe externa não precisa saber como o objeto interno funciona
- Os usuários interagem com uma interface pública limpa
- As implementações internas podem ser trocadas sem alterar a interface pública
Experimente você mesmo
-- main.lua
-- Junte tudo!
local Speaker = require('Speaker')
local MusicPlayer = require('MusicPlayer')
-- Ler entradas
local volume = tonumber(io.read())
local brand = io.read()
local trackName = io.read()
-- TODO: Criar um Speaker com o volume fornecido
-- TODO: Criar um MusicPlayer com a marca e o alto-falante
-- TODO: Chamar o método play do player com o nome da faixa
-- TODO: Chamar o método stop do player
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
1O Conceito 'Self'
Tabelas com Funções'self' ExplícitoA Sintaxe de Dois-pontosPonto vs Dois-pontosRecapitulação - Movendo o Ponto4Projeto: Banco Digital
Configuração do ProjetoMétodo de Depósito7Polimorfismo e Sobrescrita
Sobrescrita de MétodosChamando Métodos da Classe PaiDuck TypingInterface ComumVerificando o TipoRecapitulação - Papéis de Funcionários10Projeto: Gerenciador de Formas
Configuração do ProjetoClasse Retângulo2Padrão de Protótipo de Classe
O Conceito de ProtótipoVinculando com __indexO Construtor :new()Inicializando AtributosInstâncias IndependentesRecapitulação - Fábrica de Carros5Sobrecarga de Operadores em POO
Somando ObjetosSubtraindo ObjetosConcatenando ObjetosComparando Objetos (<, >)Recapitulação - Matemática de Carteira8Encapsulamento
Convenções de NomenclaturaClosures para PrivacidadeAcesso via ClosuresTabelas Somente LeituraLógica de ValidaçãoRecapitulação - Cofre Seguro11Padrões de Projeto (Lite)
Funções FactoryTabela SingletonPadrão IteratorObserver (Listener)Recapitulação - Logger Factory3Estado e Comportamento do Objeto
Variáveis de InstânciaMétodos GetterMétodos SetterPropriedades CalculadasFormatação de StringsVerificações de IgualdadeRecapitulação - Nota do Aluno6Fundamentos de Herança
Configurando a HerançaHerdando MétodosEstendendo o ConstrutorAdicionando Métodos FilhosCompartilhado vs ÚnicoRecapitulação - Hierarquia de Formas9Composição e Mixins
Relacionamento Tem-UmDelegaçãoMixins SimplesAplicando Múltiplos MixinsMixins vs HerançaRecapitulação - Montagem de Robô