Menu
Coddy logo textTech

Herdando Métodos

Parte da seção Object Oriented Programming do Journey de Lua da Coddy — lição 32 de 70.

Com o link de herança estabelecido, as instâncias da classe filha ganham acesso automaticamente a todos os métodos da classe pai. Isso acontece através da cadeia de busca (lookup chain) do Lua — quando você chama um método em uma instância, o Lua pesquisa em cada tabela conectada até encontrar o que você está procurando.

Considere esta configuração onde Animal define um método :breathe():

local Animal = {}
Animal.__index = Animal

function Animal:new()
    local obj = {}
    setmetatable(obj, Animal)
    return obj
end

function Animal:breathe()
    print("Breathing...")
end

-- Dog herda de Animal
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new()
    local obj = {}
    setmetatable(obj, Dog)
    return obj
end

Agora veja o que acontece quando criamos um Dog e chamamos o método da classe pai:

local buddy = Dog:new()
buddy:breathe()  -- Saída: Respirando...

A classe Dog nunca definiu :breathe(), mas ainda assim funciona. Lua primeiro verifica buddy, não encontra nada, então verifica Dog, ainda nada, e finalmente o encontra em Animal. Essa herança automática de métodos significa que você escreve o comportamento compartilhado uma vez no pai e cada classe filha se beneficia imediatamente.

challenge icon

Desafio

Fácil

Vamos construir uma hierarquia simples de criaturas para ver a herança de métodos em ação! Você criará uma classe pai Animal e uma classe filha Dog, e então demonstrará que as instâncias de Dog podem usar métodos definidos apenas em Animal.

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

  • Animal.lua: Defina sua classe pai com o padrão de classe padrão. Inclua um construtor :new(name) que armazena o nome do animal e um método :speak() que imprime o nome do animal seguido por makes a sound. Retorne a classe ao final do arquivo.
  • Dog.lua: Defina sua classe filha que herda de Animal. Importe o módulo Animal e configure o link de herança para que Dog possa acessar os métodos de Animal. Inclua um construtor :new(name) que armazena o nome e define Dog como a metatabela. A classe Dog NÃO deve definir seu próprio método :speak() — ela herdará isso de Animal.
  • main.lua: Importe seu módulo Dog, leia um nome da entrada, crie uma instância de Dog com esse nome e chame o método :speak() nela.

Você receberá uma entrada: o nome do cachorro.

Por exemplo, se a entrada for Buddy, a saída deve ser:

Buddy makes a sound

A mágica aqui é que sua classe Dog nunca define :speak(), mas chamá-lo em uma instância de Dog funciona perfeitamente. Lua segue a cadeia de busca da instância de Dog para a classe Dog, e depois para a classe Animal, onde encontra o método. Isso é a herança em ação!

Folha de consulta

Instâncias de classes filhas ganham acesso automaticamente a todos os métodos da classe pai através da cadeia de busca do Lua. Quando um método é chamado em uma instância, o Lua pesquisa em cada tabela conectada até encontrar o método.

Configurando Herança

Definição da 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 com link de herança:

local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new()
    local obj = {}
    setmetatable(obj, Dog)
    return obj
end

Usando Métodos Herdados

Instâncias filhas podem chamar métodos da classe pai mesmo que não estejam definidos na classe filha:

local buddy = Dog:new()
buddy:breathe()  -- Saída: Breathing...

A cadeia de busca: Lua verifica buddyDogAnimal até que o método seja encontrado.

Organização de Classes em Múltiplos Arquivos

Arquivo da classe pai (Animal.lua):

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

return Animal

Arquivo da classe filha (Dog.lua):

local Animal = require("Animal")

local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new(name)
    local obj = {name = name}
    setmetatable(obj, Dog)
    return obj
end

return Dog

Uso no arquivo principal:

local Dog = require("Dog")
local buddy = Dog:new("Buddy")
buddy:speak()  -- Saída: Buddy makes a sound

Experimente você mesmo

-- main.lua: Ponto de entrada

local Dog = require('Dog')

-- Lê o nome do cachorro da entrada
local name = io.read()

-- TODO: Criar uma instância de Dog com o nome fornecido

-- TODO: Chamar o método :speak() na instância do cachorro
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 Object Oriented Programming