Проверка на равенство
Часть раздела Объектно-ориентированное программирование путешествия по Lua на Coddy. Урок 17 из 70.
Вы уже видели, как __tostring управляет отображением объекта. Ещё один полезный метаметод — __eq, который определяет, когда два объекта следует считать равными с помощью оператора ==.
По умолчанию сравнение двух таблиц с помощью == проверяет, является ли это одна и та же таблица в памяти. Два отдельных объекта с идентичными данными вернут значение false:
local user1 = {id = 101, name = "Alice"}
local user2 = {id = 101, name = "Alice"}
print(user1 == user2) -- Вывод: false (разные таблицы)С помощью __eq можно определить собственную логику равенства. В классе его добавляют так же, как __tostring, в виде функции в таблице класса. Чтобы равенство работало, оба объекта должны использовать одну и ту же метатаблицу:
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Теперь два объекта User считаются equal, если у них одинаковый ID, независимо от других полей:
local u1 = User:new(101, "Alice")
local u2 = User:new(101, "Bob")
local u3 = User:new(202, "Alice")
print(u1 == u2) -- Вывод: true (тот же ID)
print(u1 == u3) -- Вывод: false (разные ID)Этот шаблон полезен, когда объекты представляют сущности реального мира с уникальными идентификаторами: при сравнении записей базы данных, игровых сущностей или любых объектов, для которых идентичность важнее расположения в памяти.
Задание
ЛегкоДавайте создадим класс Product, который может определить, являются ли два продукта одним и тем же товаром, даже если они хранятся в совершенно разных таблицах! В розничных системах продукты часто имеют уникальные коды SKU (Stock Keeping Units), и два продукта следует считать равными, если у них один и тот же SKU, независимо от других деталей, таких как изменения цены.
Вы организуете код в двух файлах:
Product.lua: Определите свой классProductсо стандартным шаблоном prototype. Каждый продукт должен хранитьsku(уникальный идентификатор) иname. Implement метаметод__eq, чтобы два продукта считались равными, если у них один и тот же SKU: имя не имеет значения для равенства.main.lua: Подключите свой модуль Product и создайте несколько экземпляров продукта. Сравните их с помощью оператора==, чтобы увидеть свой пользовательский механизм сравнения на практике.
Ваш класс Product должен включать:
- Конструктор
:new(sku, name) - Метод
:getInfo(), который возвращает строку в формате:[sku]: [name] - Метаметод
__eq, сравнивающий продукты по их SKU
Вы получите шесть входных значений:
- SKU первого продукта
- Имя первого продукта
- SKU второго продукта
- Имя второго продукта
- SKU третьего продукта
- Имя третьего продукта
В основном файле создайте три продукта, используя предоставленные входные значения, а затем выведите:
- Информацию о каждом продукте (три строки)
- result сравнения продукта 1 с продуктом 2
- result сравнения продукта 1 с продуктом 3
Например, если входными значениями являются ABC123, Wireless Mouse, ABC123, Mouse (Updated), XYZ789 и Keyboard, вывод должен быть таким:
ABC123: Wireless Mouse
ABC123: Mouse (Updated)
XYZ789: Keyboard
true
falseОбратите внимание, что первые два продукта равны (одинаковый SKU), хотя их имена различаются. Именно так реальные системы управления запасами отслеживают продукты при изменениях и обновлениях названий!
Попробуйте сами
-- Подключить модуль Product
local Product = require('Product')
-- Считать входные данные
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: Создать три экземпляра Product, используя входные данные
-- TODO: Вывести информацию о каждом продукте (три строки)
-- TODO: Вывести результат сравнения продукта 1 с продуктом 2
-- TODO: Вывести результат сравнения продукта 1 с продуктом 3
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Концепция 'self'
Таблицы с функциямиЯвный 'self'Синтаксис с двоеточиемТочка против двоеточияИтоги — Движущаяся точка4Проект: Цифровой банк
Настройка проектаМетод пополнения7Полиморфизм и переопределение
Переопределение методовВызов родительских методовУтиная типизацияОбщий интерфейсПроверка типаИтоги — Роли сотрудников2Паттерн прототипа класса
Концепция прототипаСвязывание через __indexКонструктор :new()Инициализация атрибутовНезависимые экземплярыИтоги — Автозавод5Перегрузка операторов в ООП
Сложение объектовВычитание объектовКонкатенация объектовСравнение объектов (<, >)Повторение — Математика кошелька8Инкапсуляция
Соглашения об именованииЗамыкания для приватностиДоступ через замыканияТаблицы только для чтенияЛогика валидацииИтоги — Защищенное хранилище11Паттерны проектирования (Lite)
Фабричные функцииТаблица SingletonПаттерн IteratorObserver (Слушатель)Итоги — Logger Factory3Состояние и поведение объектов
Переменные экземпляраГеттерыСеттерыВычисляемые свойстваФорматирование строкПроверка на равенствоПовторение — Оценка студента6Основы наследования
Настройка наследованияНаследование методовРасширение конструктораДобавление дочерних методовОбщее и уникальноеИтоги: Иерархия фигурПотренируйтесь самостоятельно: Онлайн-компилятор Lua