相等性检查
本课属于 Coddy Lua 学习旅程的“面向对象编程”单元。第 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 对象具有相同的 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 代码(库存单位),如果两个产品的 SKU 相同,就应将它们视为相等,无论价格变动等其他详情是否相同。
你需要将代码分布在两个文件中:
Product.lua:使用标准原型模式定义Product类。每个产品都应存储一个sku(唯一标识符)和一个name。实现__eq元方法,让 SKU 相同的两个产品被视为相等:名称不影响相等性。main.lua:引入 Product 模块,并创建多个产品实例。使用==运算符比较它们,看看自定义的相等判断逻辑如何生效。
你的 Product 类应包含:
- 一个
:new(sku, name)构造函数 - 一个
:getInfo()方法,返回格式为[sku]: [name]的字符串 - 一个根据 SKU 比较产品的
__eq元方法
你将收到 6 个输入:
- 第一个产品的 SKU
- 第一个产品的名称
- 第二个产品的 SKU
- 第二个产品的名称
- 第三个产品的 SKU
- 第三个产品的名称
在主文件中,使用提供的输入创建 3 个产品,然后输出:
- 每个产品的信息(3 行)
- 比较产品 1 和产品 2 的结果
- 比较产品 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:使用输入创建 3 个 Product 实例
-- TODO:打印每个产品的信息(共 3 行)
-- TODO:打印产品 1 与产品 2 的比较结果
-- TODO:打印产品 1 与产品 3 的比较结果
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Lua 在线编译器