Configurando a Herança
Parte da seção Object Oriented Programming do Journey de Lua da Coddy — lição 31 de 70.
Até agora, você construiu classes onde cada objeto busca métodos em uma única tabela de protótipos. Mas e se você quiser que uma classe seja construída sobre outra? É aqui que entra a herança — uma classe filha pode acessar tudo de uma classe pai enquanto adiciona seus próprios recursos.
A percepção principal é que a própria tabela de uma classe pode ter uma metatabela. Quando o Lua não consegue encontrar algo na classe filha, ele procura no __index da metatabela da filha — que aponta para a classe pai.
-- Classe pai
local Animal = {}
Animal.__index = Animal
function Animal:new()
local obj = {}
setmetatable(obj, Animal)
return obj
end
function Animal:breathe()
print("Breathing...")
endAgora, aqui está a configuração de herança. Criamos uma classe filha e definimos sua metatabela para olhar para a classe pai:
-- Classe filha
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})Esta única linha — setmetatable(Dog, {__index = Animal}) — cria o link de herança. Quando uma instância de Dog chama um método não encontrado em Dog, o Lua verifica Animal.
A cadeia de busca funciona assim: instance → Dog → Animal. Cada etapa usa __index para encontrar a próxima tabela a ser pesquisada. Isso permite que as classes filhas herdem automaticamente todos os métodos dos pais sem copiá-los.
Desafio
FácilVamos construir sua primeira hierarquia de herança! Você criará um relacionamento simples de classe pai-filho onde uma classe Machine serve como base, e uma classe Robot herda dela.
Você organizará seu código em três arquivos:
Machine.lua: Defina sua classe pai com o padrão de classe padrão. Inclua um construtor:new()e um método:status()que imprimeMachine is operational. Não se esqueça de configurar o__indexe retornar a classe ao final do arquivo.Robot.lua: Defina sua classe filha que herda de Machine. Requeira o módulo Machine, configure a tabela Robot com seu próprio__indexe estabeleça o link de herança usandosetmetatable(Robot, {__index = Machine}). Inclua um construtor:new()que cria uma instância com Robot como sua metatabela.main.lua: Reúna tudo requerendo seu módulo Robot, criando uma instância de Robot e chamando o método:status()herdado.
O conceito principal aqui é que sua classe Robot não define :status() por si mesma — ela herda este método de Machine através da cadeia de metatabelas. Quando você chama :status() em uma instância de Robot, o Lua procurará em Robot primeiro, não o encontrará e, em seguida, seguirá o link __index para Machine, onde descobrirá o método.
Sua saída deve ser:
Machine is operationalEsta única linha prova que a herança está funcionando — seu Robot acessou com sucesso um método definido apenas em sua classe pai!
Folha de consulta
Para criar herança em Lua, defina a metatabela de uma tabela de classe para apontar para a classe pai usando __index:
-- Classe pai
local Animal = {}
Animal.__index = Animal
function Animal:new()
local obj = {}
setmetatable(obj, Animal)
return obj
end
function Animal:breathe()
print("Breathing...")
end
-- Classe filha
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})O link de herança é criado com setmetatable(Dog, {__index = Animal}). Isso permite que instâncias de Dog acessem métodos de Animal automaticamente.
A cadeia de busca segue: instância → Classe filha → Classe pai. Cada etapa usa __index para encontrar a próxima tabela a ser pesquisada.
Experimente você mesmo
-- main.lua: Reúne tudo
-- TODO: Requerer o módulo Robot
-- TODO: Criar uma instância de Robot usando Robot:new()
-- TODO: Chamar o método herdado :status() na sua instância de robô
-- Isso deve imprimir "Machine is operational"
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