🚀 Metamétodos

Personalize como suas tabelas se comportam com operadores e funções!

🚀

O que são metamétodos?

Metamétodos são funções "mágicas" que mudam como uma tabela funciona. Por exemplo: e se você pudesse somar duas tabelas com +?

A "metatabela" é uma tabela especial que contém esses poderes mágicos.

Configurando uma metatabela

local minha_tabela = {}
local minha_meta = {}

-- Associa a metatabela
defina_metatabela(minha_tabela, minha_meta)

__soma: Adição (+)

Permite usar + entre duas tabelas:

local mt = {
    __soma = função(a, b)
        retorne {x = a.x + b.x, y = a.y + b.y}
    fim
}

local v1 = {x = 10, y = 20}
local v2 = {x = 5, y = 5}

defina_metatabela(v1, mt)
defina_metatabela(v2, mt)

local v3 = v1 + v2
exiba(v3.x, v3.y)   -- 15, 25

__subtração: Subtração (-)

local mt = {
    __subtração = função(a, b)
        retorne {x = a.x - b.x, y = a.y - b.y}
    fim
}

local resultado = v1 - v2

__índice: Acessando campos que não existem

É chamado quando você tenta acessar algo que não está na tabela:

local padrao = {cor = "azul", tamanho = "médio"}

local mt = {
    __índice = padrao  -- Busca aqui se não encontrar
}

local camisa = {tamanho = "grande"}
defina_metatabela(camisa, mt)

exiba(camisa.tamanho)  -- "grande" (está na tabela)
exiba(camisa.cor)      -- "azul" (buscou no padrão!)
O __índice é a base da herança em Sol! Permite criar "classes" e objetos.

__novo_índice: Controlando atribuições

É chamado quando você tenta criar um campo novo:

local mt = {
    __novo_índice = função(tabela, chave, valor)
        exiba("Tentou criar: " .. chave .. " = " .. converta_para_texto(valor))
        -- Não faz nada! Campo não é criado.
    fim
}

local bloqueada = {}
defina_metatabela(bloqueada, mt)

bloqueada.novo = 123  -- Mostra mensagem, mas não cria!
exiba(bloqueada.novo)  -- nulo

__chame: Chamando tabela como função

Permite usar tabela() como se fosse uma função:

local mt = {
    __chame = função(ego, x)
        retorne x * ego.fator
    fim
}

local multiplicador = {fator = 3}
defina_metatabela(multiplicador, mt)

exiba(multiplicador(10))  -- 30

__converta_para_texto: Conversão para texto

Controla o que aparece quando você converte para texto:

local mt = {
    __converta_para_texto = função(p)
        retorne "Pessoa: " .. p.nome .. " (" .. p.idade .. " anos)"
    fim
}

local pessoa = {nome = "Ana", idade = 12}
defina_metatabela(pessoa, mt)

exiba(pessoa)  -- Pessoa: Ana (12 anos)

Tabela completa de metamétodos

Operadores Aritméticos

NomeOperaçãoDescrição
__somaa + bAdição
__subtraçãoa - bSubtração
__multiplicaçãoa * bMultiplicação
__divisãoa / bDivisão
__divisão_inteiraa // bDivisão inteira
__móduloa % bResto da divisão
__potênciaa ^ bExponenciação
__negação-aNegativo unário

Operadores Binários (Bitwise)

NomeOperaçãoDescrição
__e_binárioa & bE binário (AND)
__ou_binárioa | bOU binário (OR)
__ou_exclusivoa ~ bOU exclusivo (XOR)
__não_binário~aNÃO binário (complemento)
__desloque_esquerdaa << bDeslocamento à esquerda
__desloque_direitaa >> bDeslocamento à direita

Operadores de Comparação

NomeOperaçãoDescrição
__iguala == bIgualdade
__menor_quea < bMenor que
__menor_ou_iguala <= bMenor ou igual
Os operadores > e >= são derivados de __menor_que e __menor_ou_igual. Não precisam de metamétodos próprios!

Outros Operadores

NomeOperaçãoDescrição
__concatenea .. bConcatenação
__comprimento#aOperador de tamanho

Acesso e Controle

NomeQuando É chamado
__índiceLer campo inexistente
__novo_índiceCriar/modificar campo inexistente
__chameChamar tabela como função
__converta_para_textoConverter para texto

Gerenciamento de Memária e Ciclo de Vida

NomeQuando É chamado
__coletor_lixoQuando objeto é coletado pelo GC (finalizador)
__fecheQuando variável to-be-closed sai de escopo
__modoDefine se tabela tem chaves/valores fracos ("k", "v", "kv")

Exemplo: Operadores Binários

local mt = {
    __e_binário = função(a, b)
        retorne a.bits & b.bits
    fim,
    __ou_binário = função(a, b)
        retorne a.bits | b.bits
    fim
}

local flags1 = {bits = 0b1010}
local flags2 = {bits = 0b1100}

defina_metatabela(flags1, mt)
defina_metatabela(flags2, mt)

exiba(flags1 & flags2)  -- 0b1000 (8)
exiba(flags1 | flags2)  -- 0b1110 (14)

Exemplo: Finalizador (__coletor_lixo)

local mt = {
    __coletor_lixo = função(ego)
        exiba("Limpando recurso: " .. ego.nome)
        -- Fechar arquivo, conexão, etc.
    fim
}

local recurso = {nome = "arquivo.txt"}
defina_metatabela(recurso, mt)

recurso = nulo  -- Será coletado eventualmente
colete_lixo()  -- Força coleta

Exemplo: Variável To-Be-Closed (__feche)

local mt = {
    __feche = função(ego)
        exiba("Fechando: " .. ego.nome)
    fim
}

função use_recurso()
    local arquivo a_fechar = defina_metatabela({nome = "dados.txt"}, mt)
    -- Usa arquivo...
    -- __feche É chamado automaticamente ao sair do escopo
fim

use_recurso()  -- Exibe: "Fechando: dados.txt"

Exemplo: Tabela Fraca (__modo)

-- Tabela com chaves fracas (não impede coleta das chaves)
local cache = {}
defina_metatabela(cache, {__modo = "k"})

local chave = {id = 1}
cache[chave] = "valor"

chave = nulo  -- Chave pode ser coletada
colete_lixo()
-- cache agora está vazio

Exemplo: Criando uma "classe" Vetor

local Vetor = {}
Vetor.__índice = Vetor

função Vetor.novo(x, y)
    local ego = {x = x, y = y}
    defina_metatabela(ego, Vetor)
    retorne ego
fim

função Vetor:magnitude()
    retorne matemática.obtenha_raiz_quadrada(ego.x^2 + ego.y^2)
fim

função Vetor.__soma(a, b)
    retorne Vetor.novo(a.x + b.x, a.y + b.y)
fim

função Vetor.__multiplicação(a, escalar)
    se obtenha_tipo(escalar) == "número" então
        retorne Vetor.novo(a.x * escalar, a.y * escalar)
    fim
fim

função Vetor.__converta_para_texto(v)
    retorne "Vetor(" .. v.x .. ", " .. v.y .. ")"
fim

-- Usando
local v1 = Vetor.novo(3, 4)
local v2 = Vetor.novo(1, 2)

exiba(v1)              -- Vetor(3, 4)
exiba(v1:magnitude())  -- 5
exiba(v1 + v2)         -- Vetor(4, 6)
exiba(v1 * 2)          -- Vetor(6, 8)
Metamétodos são a chave para criar código flexível e elegante em Sol!
Cuidado: metamétodos podem tornar o código difácil de entender se usados em excesso. Use com moderação!
```