Somando Objetos
Parte da seção Object Oriented Programming do Journey de Lua da Coddy — lição 26 de 70.
Você já viu como metamétodos como __tostring e __eq permitem que você personalize como os objetos se comportam. Agora vamos estender isso para operações aritméticas, começando com a adição.
O metamétodo __add define o que acontece quando você usa o operador + entre dois objetos. Quando o Lua vê a + b, ele procura por __add na metatabela de qualquer um dos operandos.
local Vector = {}
Vector.__index = Vector
function Vector:new(x, y)
local obj = {x = x, y = y}
setmetatable(obj, Vector)
return obj
end
function Vector.__add(v1, v2)
return Vector:new(v1.x + v2.x, v1.y + v2.y)
endObserve que __add é definido com um ponto, não dois-pontos. Ele recebe ambos os operandos como argumentos e deve retornar um novo objeto em vez de modificar qualquer um dos originais. Isso mantém a operação previsível e segura.
local a = Vector:new(3, 4)
local b = Vector:new(1, 2)
local c = a + b
print(c.x, c.y) -- Saída: 4 6A principal percepção é que __add deve estar na própria metatabela (aqui, Vector), não apenas no objeto. Como definimos Vector como a metatabela para todas as instâncias, todas elas compartilham esse comportamento automaticamente.
Desafio
FácilVamos construir uma classe Vector que suporte a adição usando o operador +. Este é o seu primeiro passo na sobrecarga de operadores — fazendo com que seus objetos funcionem naturalmente com os operadores integrados do Lua.
Você organizará seu código em dois arquivos:
Vector.lua: Defina sua classe Vector com os componentesxey. Inclua um construtor:new(x, y)e implemente o metamétodo__addpara que a soma de dois vetores crie um novo vetor com os componentes combinados. Lembre-se de que__addusa a sintaxe de ponto (não dois-pontos) e recebe ambos os operandos como argumentos.main.lua: Importe seu módulo Vector, crie instâncias de vetores e demonstre que somá-los produz o resultado correto.
Você receberá quatro entradas:
- Componente x do primeiro vetor
- Componente y do primeiro vetor
- Componente x do segundo vetor
- Componente y do segundo vetor
No seu arquivo principal, crie dois vetores com os componentes fornecidos, some-os usando o operador + e imprima os valores x e y do vetor resultante em linhas separadas.
Por exemplo, se as entradas forem 3, 4, 1, 2, a saída deve ser:
4
6O primeiro vetor (3, 4) mais o segundo vetor (1, 2) é igual a um novo vetor (4, 6).
Folha de consulta
O metamétodo __add define o que acontece quando você usa o operador + entre dois objetos.
Quando o Lua vê a + b, ele procura por __add na metatabela de qualquer um dos operandos.
local Vector = {}
Vector.__index = Vector
function Vector:new(x, y)
local obj = {x = x, y = y}
setmetatable(obj, Vector)
return obj
end
function Vector.__add(v1, v2)
return Vector:new(v1.x + v2.x, v1.y + v2.y)
end__add é definido com um ponto, não com dois-pontos. Ele recebe ambos os operandos como argumentos e deve retornar um novo objeto em vez de modificar qualquer um dos originais.
local a = Vector:new(3, 4)
local b = Vector:new(1, 2)
local c = a + b
print(c.x, c.y) -- Saída: 4 6__add deve estar na própria metatabela, não apenas no objeto.
Experimente você mesmo
-- Requer o módulo Vector
local Vector = require('Vector')
-- Lê a entrada
local x1 = tonumber(io.read())
local y1 = tonumber(io.read())
local x2 = tonumber(io.read())
local y2 = tonumber(io.read())
-- TODO: Criar duas instâncias de Vector usando os valores de entrada
-- TODO: Somar os dois vetores usando o operador +
-- TODO: Imprimir os valores x e y do vetor resultante em linhas separadas
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