0Pricing
Lua Academy · Aula

Classes com metatabelas

Simule classes usando tabelas e __index para localizar métodos.

Classes com metatabelas é uma aula grátis de Lua Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Lua Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Lua Academy inclui 4 aulas no total.

Padrão de tabela de classe

Em Lua, uma “classe” é apenas uma tabela que armazena métodos. As instâncias são tabelas cujo metatable tem __index apontando para a tabela da classe. Isso torna todos os métodos acessíveis nas instâncias por meio da cadeia de busca.

local Animal = {}
Animal.__index = Animal

function Animal.new(name, sound)
  return setmetatable({name=name, sound=sound}, Animal)
end

function Animal:speak()
  print(self.name .. " says " .. self.sound)
end

local dog = Animal.new("Rex","Woof")
dog:speak()  -- Rex says Woof

__index aponta para a classe

Definir ClassName.__index = ClassName significa “procurar chaves ausentes na tabela da classe”. Quando um método da instância é chamado, Lua não o encontra na instância, verifica o metatable (__index), encontra a classe e procura o método nela.

local Point = {}
Point.__index = Point

Point.type = "2D Point"

function Point.new(x,y)
  return setmetatable({x=x,y=y}, Point)
end

function Point:magnitude()
  return math.sqrt(self.x^2 + self.y^2)
end

local p = Point.new(3,4)
print(p:magnitude())   -- 5.0
print(p.type)          -- 2D Point (from class)

Padrão de construtor

A função new() é o construtor: ela cria uma tabela com dados da instância e a retorna envolvida em um metatable que aponta para a classe. Essa é a maneira padrão de criar objetos em Lua.

local Circle = {}
Circle.__index = Circle

function Circle.new(cx, cy, radius)
  assert(radius > 0, "radius must be positive")
  return setmetatable({cx=cx, cy=cy, r=radius}, Circle)
end

function Circle:area()
  return math.pi * self.r^2
end

function Circle:perimeter()
  return 2 * math.pi * self.r
end

local c = Circle.new(0, 0, 5)
print(string.format("Area: %.2f", c:area()))

Sintaxe de método versus função

obj:method() é uma forma abreviada de obj.method(obj). Defina métodos com a sintaxe de dois-pontos (function Cls:method()) para obter um self implícito. Chame-os com dois-pontos para passar a instância. Misturar ponto e dois-pontos causa erros sutis.

local Dog = {}
Dog.__index = Dog

-- Define with colon: self is implicit
function Dog:bark(times)
  for i = 1, (times or 1) do
    print(self.name .. ": Woof!")
  end
end

function Dog.new(name)
  return setmetatable({name=name}, Dog)
end

local d = Dog.new("Buddy")
d:bark(2)        -- Buddy: Woof! (x2)
-- Dog.bark(d,1) -- same thing, explicit self

Campos no nível da classe versus da instância

Os campos da tabela da classe são compartilhados por todas as instâncias (variáveis da classe). Os campos da tabela da instância são específicos de cada instância. Uma instância pode ocultar um campo da classe criando seu próprio campo com o mesmo nome.

local Entity = {}
Entity.__index = Entity
Entity.count = 0    -- class-level counter

function Entity.new(name)
  Entity.count = Entity.count + 1
  return setmetatable({name=name, id=Entity.count}, Entity)
end

local a = Entity.new("alpha")
local b = Entity.new("beta")
local c = Entity.new("gamma")

print(Entity.count)  -- 3
print(a.id, b.id, c.id)  -- 1  2  3

tostring para classes

Adicione __tostring à tabela da classe para obter uma saída de impressão legível. Como o metatable da instância é a classe, e a classe tem __tostring, todas as instâncias o usarão automaticamente.

local Vec2 = {}
Vec2.__index = Vec2
Vec2.__tostring = function(v)
  return string.format("Vec2(%g, %g)", v.x, v.y)
end

function Vec2.new(x,y)
  return setmetatable({x=x,y=y}, Vec2)
end

function Vec2.__add(a, b)
  return Vec2.new(a.x+b.x, a.y+b.y)
end

local v1 = Vec2.new(1,2)
local v2 = Vec2.new(3,4)
print(v1+v2)   -- Vec2(4, 6)

Verificando o tipo da instância

Verifique se um objeto é uma instância de uma classe comparando seu metatable com a tabela da classe. Esse é o equivalente de instanceof em Lua.

local Dog = {}
Dog.__index = Dog

function Dog.new(name)
  return setmetatable({name=name}, Dog)
end

local function isDog(obj)
  return getmetatable(obj) == Dog
end

local d = Dog.new("Rex")
local t = {}
print(isDog(d))  -- true
print(isDog(t))  -- false

Métodos privados

Métodos privados são funções locais no arquivo do módulo. Eles não podem ser chamados de fora, mas ficam acessíveis dentro dos métodos públicos do módulo como valores externos.

local Account = {}
Account.__index = Account

-- Private helper
local function validate(amount)
  return type(amount)=="number" and amount > 0
end

function Account.new(balance)
  return setmetatable({balance=balance or 0}, Account)
end

function Account:deposit(amount)
  assert(validate(amount), "invalid amount")
  self.balance = self.balance + amount
end

function Account:getBalance() return self.balance end

Comparação de classes

Sobrecarregue __eq e __lt para personalizar a igualdade e a ordenação. Lua só chama __eq para tabelas quando os dois operandos compartilham o mesmo metatable.

local Temp = {}
Temp.__index = Temp
Temp.__eq = function(a,b) return a.celsius == b.celsius end
Temp.__lt = function(a,b) return a.celsius < b.celsius end
Temp.__tostring = function(t)
  return t.celsius.."°C"
end

function Temp.new(c)
  return setmetatable({celsius=c}, Temp)
end

local t1 = Temp.new(100)
local t2 = Temp.new(0)
print(t1 == Temp.new(100))  -- true
print(t2 < t1)              -- true

Várias classes

Cada classe é uma tabela independente com seu próprio metatable. Objetos de classes diferentes têm metatables diferentes. Essa é a base de um sistema de POO com várias classes em Lua.

local Cat = {}
Cat.__index = Cat

function Cat.new(name) return setmetatable({name=name,lives=9},Cat) end
function Cat:loseLife() self.lives=self.lives-1; return self.lives end

local Dog2 = {}
Dog2.__index = Dog2
function Dog2.new(name) return setmetatable({name=name,tricks={}},Dog2) end
function Dog2:learn(t) self.tricks[#self.tricks+1]=t end

local c = Cat.new("Whiskers")
local d = Dog2.new("Buddy")
d:learn("sit"); d:learn("stay")
print(c:loseLife(), #d.tricks)  -- 8  2

Verificação rápida

Por que definimos ClassName.__index = ClassName?

Recapitulação: classes por meio de metatables

Resumo:

  • Classe = tabela + __index = self
  • Construtor: function Cls.new(...) return setmetatable({}, Cls) end
  • Métodos: definidos na tabela da classe e chamados com a sintaxe de dois-pontos
  • Campos da classe versus da instância: campos da classe compartilhados, campos da instância específicos de cada objeto
  • Verificação de tipo: getmetatable(obj) == Cls

Perguntas Frequentes

A aula “Classes com metatabelas” é grátis?

Sim — o texto completo de “Classes com metatabelas” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Lua Academy, atualize para CoddyKit PRO. O curso de Lua Academy inclui 4 aulas no total.

O que vou aprender em “Classes com metatabelas”?

Simule classes usando tabelas e __index para localizar métodos. Você pratica Lua Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Lua Academy?

Nenhuma experiência prévia é necessária. Lua Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “Classes com metatabelas”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Lua Academy?

Sim. Cada aula de Lua Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Classes com metatabelas
  2. Construtores e new()
  3. Métodos de instância e self
  4. Encapsulamento com fechamentos
← Voltar para Lua Academy