Sobrescrita de Métodos
Parte da seção Object Oriented Programming do Journey de Lua da Coddy — lição 37 de 70.
Até agora, as classes filhas herdaram métodos das classes pai e adicionaram novos. Mas e se uma classe filha precisar do mesmo nome de método com um comportamento diferente? Isso é chamado de method overriding (sobrescrita de método).
Quando você define um método em uma classe filha com o mesmo nome de um na classe pai, a versão da filha tem prioridade. A cadeia de busca do Lua verifica a classe filha primeiro — se encontrar o método lá, ela para de procurar.
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local obj = {name = name}
setmetatable(obj, Animal)
return obj
end
function Animal:speak()
print(self.name .. " makes a sound")
end
-- Dog sobrescreve speak()
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new(name)
local obj = Animal.new(Animal, name)
setmetatable(obj, Dog)
return obj
end
function Dog:speak()
print(self.name .. " barks: Woof!")
endAgora cada classe responde de forma diferente à mesma chamada de método:
local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")
generic:speak() -- Saída: Creature faz um som
buddy:speak() -- Saída: Buddy late: Woof!O :speak() do Dog substitui completamente a versão do pai para instâncias de Dog. Isso permite que você crie um comportamento especializado enquanto mantém uma interface consistente — cada animal pode :speak(), mas cada espécie o faz de forma diferente.
Desafio
FácilVamos construir um pequeno reino animal onde diferentes criaturas falam de suas próprias maneiras únicas! Você criará uma classe pai Animal e duas classes filhas—Cat e Cow—que substituem o método :speak() do pai por seu próprio comportamento especializado.
Você organizará seu código em quatro arquivos:
Animal.lua: Sua classe base com um construtor:new(name)que armazena o nome do animal. Inclua um método:speak()que imprime o nome do animal seguido pormakes a sound. Este é o comportamento padrão que as classes filhas irão sobrescrever.Cat.lua: Uma classe filha que herda de Animal. Seu construtor:new(name)deve chamar o construtor pai e, em seguida, vincular novamente a metatabela para Cat. Sobrescreva o método:speak()para que os gatos digam algo diferente—imprima o nome do gato seguido pormeows: Meow!Cow.lua: Outra classe filha que herda de Animal. Configure o construtor da mesma forma que Cat. Sobrescreva:speak()para que as vacas imprimam seu nome seguido pormoos: Moo!main.lua: Reúna tudo! Leia dois nomes da entrada, crie um Cat com o primeiro nome e uma Cow com o segundo nome, então chame:speak()em cada um para demonstrar que o mesmo nome de método produz saídas diferentes dependendo da classe.
Você receberá duas entradas:
- O nome do gato
- O nome da vaca
No seu arquivo principal, crie ambos os animais e chame :speak() primeiro no gato e depois na vaca.
Por exemplo, se as entradas forem Whiskers e Bessie, a saída deve ser:
Whiskers meows: Meow!
Bessie moos: Moo!Observe como ambos os animais respondem à mesma chamada de método :speak(), mas cada um produz uma saída específica para o seu tipo. A versão do Cat substitui completamente o comportamento genérico "makes a sound" do pai, assim como a do Cow. Isso é a sobrescrita de método em ação—mesma interface, implementações diferentes!
Folha de consulta
A sobreposição de métodos (method overriding) permite que uma classe filha defina um método com o mesmo nome de um método pai, substituindo o comportamento do pai por uma funcionalidade especializada.
Quando o Lua procura por um método, ele verifica primeiro a classe filha. Se encontrar o método lá, ele usa essa versão e para de procurar na classe pai.
Exemplo básico de sobreposição de métodos:
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local obj = {name = name}
setmetatable(obj, Animal)
return obj
end
function Animal:speak()
print(self.name .. " makes a sound")
end
-- Dog overrides speak()
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new(name)
local obj = Animal.new(Animal, name)
setmetatable(obj, Dog)
return obj
end
function Dog:speak()
print(self.name .. " barks: Woof!")
endUsando o método sobreposto:
local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")
generic:speak() -- Output: Creature makes a sound
buddy:speak() -- Output: Buddy barks: Woof!O método da classe filha substitui completamente a versão do pai para instâncias dessa classe filha, permitindo um comportamento especializado enquanto mantém uma interface consistente em todas as classes.
Experimente você mesmo
-- main.lua: Reúne tudo
local Cat = require('Cat')
local Cow = require('Cow')
-- Ler entrada
local catName = io.read()
local cowName = io.read()
-- TODO: Criar um Cat com o primeiro nome
-- TODO: Criar um Cow com o segundo nome
-- TODO: Chamar :speak() no gato primeiro, depois na vaca
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 Formas