Verificações de Igualdade
Parte da seção Object Oriented Programming do Journey de Lua da Coddy — lição 17 de 70.
Você viu como __tostring controla como um objeto se exibe. Outro metamétodo útil é __eq, que define quando dois objetos devem ser considerados iguais usando o operador ==.
Por padrão, comparar duas tabelas com == verifica se elas são exatamente a mesma tabela na memória. Dois objetos distintos com dados idênticos retornarão false:
local user1 = {id = 101, name = "Alice"}
local user2 = {id = 101, name = "Alice"}
print(user1 == user2) -- Saída: false (tabelas diferentes)Com __eq, você pode definir sua própria lógica de igualdade. Em uma classe, você o adiciona exatamente como __tostring—como uma função na tabela da classe. Para que a igualdade funcione, ambos os objetos devem compartilhar a mesma metatabela:
local User = {}
User.__index = User
function User:new(id, name)
local instance = {}
setmetatable(instance, self)
instance.id = id
instance.name = name
return instance
end
function User:__eq(other)
return self.id == other.id
endAgora, dois objetos User são considerados iguais se compartilharem o mesmo ID, independentemente de outros campos:
local u1 = User:new(101, "Alice")
local u2 = User:new(101, "Bob")
local u3 = User:new(202, "Alice")
print(u1 == u2) -- Saída: true (mesmo ID)
print(u1 == u3) -- Saída: false (IDs diferentes)Este padrão é valioso quando objetos representam entidades do mundo real com identificadores únicos — comparando registros de banco de dados, entidades de jogo ou quaisquer objetos onde a identidade importa mais do que a localização na memória.
Desafio
FácilVamos construir uma classe Product que possa determinar se dois produtos são o mesmo item — mesmo quando estão armazenados em tabelas completamente diferentes! Em sistemas de varejo, os produtos geralmente possuem códigos SKU (Stock Keeping Units) exclusivos, e dois produtos devem ser considerados iguais se compartilharem o mesmo SKU, independentemente de outros detalhes, como alterações de preço.
Você organizará seu código em dois arquivos:
Product.lua: Defina sua classeProductcom o padrão de protótipo padrão. Cada produto deve armazenar umsku(o identificador exclusivo) e umname. Implemente o metamétodo__eqpara que dois produtos sejam considerados iguais quando tiverem o mesmo SKU — o nome não importa para a igualdade.main.lua: Importe seu módulo Product e crie várias instâncias de produtos. Compare-as usando o operador==para ver sua lógica de igualdade personalizada em ação.
Sua classe Product deve incluir:
- Um construtor
:new(sku, name) - Um método
:getInfo()que retorna uma string no formato:[sku]: [name] - O metamétodo
__eqque compara produtos por seu SKU
Você receberá seis entradas:
- SKU para o primeiro produto
- Nome para o primeiro produto
- SKU para o segundo produto
- Nome para o segundo produto
- SKU para o terceiro produto
- Nome para o terceiro produto
Em seu arquivo principal, crie três produtos usando as entradas fornecidas e, em seguida, imprima:
- As informações de cada produto (três linhas)
- O resultado da comparação do produto 1 com o produto 2
- O resultado da comparação do produto 1 com o produto 3
Por exemplo, se as entradas forem ABC123, Wireless Mouse, ABC123, Mouse (Updated), XYZ789 e Keyboard, a saída deve ser:
ABC123: Wireless Mouse
ABC123: Mouse (Updated)
XYZ789: Keyboard
true
falseObserve como os dois primeiros produtos são iguais (mesmo SKU), embora seus nomes sejam diferentes — é exatamente assim que os sistemas de inventário reais rastreiam produtos por meio de alterações de nome e atualizações!
Folha de consulta
O metamétodo __eq define uma lógica de igualdade personalizada para objetos usando o operador ==.
Por padrão, comparar duas tabelas verifica se elas são a mesma tabela na memória:
local user1 = {id = 101, name = "Alice"}
local user2 = {id = 101, name = "Alice"}
print(user1 == user2) -- Output: false (different tables)Para definir uma igualdade personalizada, adicione __eq como uma função na tabela da classe. Ambos os objetos devem compartilhar a mesma metatabela:
local User = {}
User.__index = User
function User:new(id, name)
local instance = {}
setmetatable(instance, self)
instance.id = id
instance.name = name
return instance
end
function User:__eq(other)
return self.id == other.id
endAgora os objetos são iguais com base na sua lógica personalizada:
local u1 = User:new(101, "Alice")
local u2 = User:new(101, "Bob")
local u3 = User:new(202, "Alice")
print(u1 == u2) -- Output: true (same ID)
print(u1 == u3) -- Output: false (different IDs)Experimente você mesmo
-- Requer o módulo Product
local Product = require('Product')
-- Lê as entradas
local sku1 = io.read()
local name1 = io.read()
local sku2 = io.read()
local name2 = io.read()
local sku3 = io.read()
local name3 = io.read()
-- TODO: Criar três instâncias de Product usando as entradas
-- TODO: Imprimir as informações de cada produto (três linhas)
-- TODO: Imprimir o resultado da comparação do produto 1 com o produto 2
-- TODO: Imprimir o resultado da comparação do produto 1 com o produto 3
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