-- Lua 中用于定义和修改表的行为的重要机制。
-- 每个表可以关联一个元表,元表中包含一些特定的元方法(metamethods),这些元方法定义了表的不同操作行为。
-- 元表可以用于实现运算符重载、自定义表的行为等。
-- 元方法
-- __index: 控制对表中不存在的索引的访问行为。
-- 当试图访问表中不存在的索引时,Lua 会查找元表中的 __index 元方法并执行。
local tb = {}
local meta = {
__index = function(table, key)
print("无该索引", key)
end
}
setmetatable(tb, meta)
print(tb[1]) -- 此时打印 无该索引 ,nil
-- __index 也可以是一张表,
-- 这种用法通常用于实现一种类似于继承或属性的机制,让一个表可以继承另一个表的属性或方法。
local tbChild = {}
local tbBase = {
["set"] = "set"
}
setmetatable(tbChild, {
__index = tbBase
})
print(tbChild["set"]) -- 此时打印set
-- __newindex: 控制对表中不存在的索引的赋值行为。
-- 当试图为表中不存在的索引赋值时,Lua 会查找元表中的 __newindex 元方法并执行
local tb = {}
local meta = {
__newindex = function (table, key, value)
print("执行赋值操作,将表里的" .. key .. "对应的值赋值为".. value)
rawset(table, key, value) -- 使用rawset设置键值对,避免无限递归调用
end
}
setmetatable(tb,meta)
tb[1] = 1 -- 打印 执行赋值操作,将表里的1对应的值赋值为1
-- __newindex 元方法可以是一张表,这种用法通常用于实现高级的数据存储和验证。
-- 当 __newindex 是一个表时,它允许你为不同的键设置不同的赋值行为或进行更复杂的操作。
local tb = {}
local mata = {
__newindex = {
name = function(table, value)
print("将表里的name赋值为".. value)
rawset(table, "name", value)
end,
age = function(table, value)
print("将表里的age赋值为".. value)
rawset(table, "age", value)
end,
}
}
setmetatable(tb, meta)
tb["name"] = "xxx" -- 执行赋值操作,将表里的name对应的值赋值为xxx
tb["age"] = 18 --执行赋值操作,将表里的age对应的值赋值为18
-- 一个只读表的设计
local readOnlyTable = {
name = "Alice",
age = 30,
}
-- 创建元表,并定义__newindex元方法,阻止赋值操作
local metatable = {
__newindex = function(table, key, value)
error("尝试修改只读表中的值:" .. key, 2)
end
}
-- 将表关联到元表
setmetatable(readOnlyTable, metatable)
-- 尝试修改只读表中的值
readOnlyTable.name = "Bob" -- 会触发错误