Menu
Coddy logo textTech

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
end

Agora, 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.

challenge icon

Desafio

Fácil

Vamos 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 classe Product com o padrão de protótipo padrão. Cada produto deve armazenar um sku (o identificador exclusivo) e um name. Implemente o metamétodo __eq para 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 __eq que compara produtos por seu SKU

Você receberá seis entradas:

  1. SKU para o primeiro produto
  2. Nome para o primeiro produto
  3. SKU para o segundo produto
  4. Nome para o segundo produto
  5. SKU para o terceiro produto
  6. Nome para o terceiro produto

Em seu arquivo principal, crie três produtos usando as entradas fornecidas e, em seguida, imprima:

  1. As informações de cada produto (três linhas)
  2. O resultado da comparação do produto 1 com o produto 2
  3. 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
false

Observe 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
end

Agora 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
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