print("******* Metatable *******")
-- print("******* 元表概念 *******")
-- 任何表变量都可以作为另一个表变量的元表
-- 任何表变量都可以有自己的元表(父表)
-- 当我们的子表中进行一些特定操作时
-- 会执行元表中的内容
-- print("******* 设置元表 *******")
meta = {}
myTable = {}
-- 设置元表函数
-- 第一个参数:子表
-- 第二个参数:元表
setmetatable(myTable, meta)
-- print("******* 特定操作 *******")
-- print("******* 特定操作-__tostring *******")
meta2 = {
-- 当子表要被当作字符串使用时,会默认调用这个元表中的__tostring方法
__tostring = function ()
return "Mr.z"
end
}
myTable2 = {}
setmetatable(myTable2, meta2)
-- 会执行 meta2 表中的 __toString 操作
print(myTable2)
meta3 = {
-- __tostring 传入参数默认将关联的表传入
__tostring = function (t)
return t.name
end, -- 注意这里有一个 逗号
-- 当子表被当作一个函数来使用时,会默认调用元表中的 __call 中的内容
-- 参数表中的第一个参数默认为 调用的子表 自己,类似于 : 的用法
__call = function (a, b)
print(a, b)
print("In __call")
end
}
myTable3 = {
name = "Miss.Z"
}
setmetatable(myTable3, meta3)
print(myTable3)
-- print("******* 特定操作-__call *******")
-- 只有在元表中实现了 __call 才能将表当作函数调用
myTable3(1)
-- print("******* 特定操作-_运算符重载 *******")
meta4 = {
-- 相当于运算符重载,当子表使用 + 运算符时,会调用该方法
-- 重载运算符 +
-- a + b, t1 表示 a, t2 表示 b
__add = function (t1, t2)
print(t1.age, t2.age)
return t1.age + t2.age
end,
-- 运算符 -: __sub
-- 运算符 *: __mul
-- 运算符 /: __div
-- 运算符 %: __mod
-- 运算符 ^: __pow
-- 运算符 ..(拼接): __concat
-- 运算符 ==: __eq
__eq = function (t1, t2)
return true;
end
-- 运算符 <: __lt
-- 运算符 <=: __le
-- 注意:条件运算符没有 !=, >, >=, 只能通过 not 取反, 但实际上不需要,
-- 因为 t1 > t2 相当于 t2 < t1,也是重载 <
--(这也是两个对象的元表一定要一致才能正确使用条件运算符的原因)
}
-- 也可以元表外声明
meta4.__sub = function (t1, t2)
print("in __subs");
end
myTable4 = {age = 1}
setmetatable(myTable4, meta4)
myTable5 = {age = 2}
print(myTable4 + myTable5)
print(myTable4 - myTable5)
-- 如果要用条件运算符来比较两个对象
-- 这两个对象的元表一定要一致,才能准确调用方法
print(myTable4 == myTable5) -- false
setmetatable(myTable5, meta4)
print(myTable4 == myTable5) -- true
-- print("******* 特定操作-__index 和 __newindex *******")
meta5 = {
age = 1,
__index = {age = 2}
-- __index = meta5 -- 这是个坑,会返回 nil,所以建议 __index 写在表外
}
-- meta5.__index = {age = 4}
-- meta5.__index = meta5
myTable6 = {}
setmetatable(myTable6, meta5)
-- __index 当子表中找不到某一个属性时
-- 会到元表中 __index 指定的表去找索引
print(myTable6.age)
-- __index 可以嵌套
meta6Father = {age = 2}
meta6 = {}
myTable7 = {}
meta6.__index = meta6Father
setmetatable(myTable7, meta6)
setmetatable(meta6, meta6Father)
print(myTable7.age)
-- __newIndex 当赋值时,如果赋值一个不存在的索引
-- 那么会把这个值赋值到 __newindex 所指的表中,不会修改自己
meta7 = {}
myTable8 = {}
setmetatable(myTable8, meta7)
myTable8.age = 1
print(myTable8.age) -- age 添加在 myTable8 中,输出为1
meta7.__newindex = {}
myTable8.name = "name"
-- name 添加在元表的__newindex指向的表中,myTable8 中没有该变量,输出为 nil
-- 否则需要设置 meta7.__index = meta7.__newindex 才可通过 myTable8 获得 name 变量
print(myTable8.name)
print(meta7.__newindex.name)
-- newindex 与 index 类似可以嵌套
-- 如果只想知道自己身上有没有这个变量忽略 __index,那么可以使用 rawget
-- 如果有返回该变量的值,否则返回 nil
print(rawget(myTable8, "age"))
print(rawget(myTable8, "name"))
-- 如果只想对自己的表进行修改忽略 __newindex 设置 ,可以对应使用 rawset
rawset(myTable8, "name", "selfName")
print(myTable8.name)
-- 其他
-- 获取元表
print(getmetatable(myTable8))
Lua-- 元表
于 2022-04-17 16:47:43 首次发布