Lua元表
概念:
- 任何变量都可以作为另一个表变量的元表
- 任何表变量都可以有自己的元表
- 当我们子表中进行一些特定操作时,会执行元表中的内容
一、设置元表
使用setmetatable(table,metaTable)
meta = {}
myTable = {}
--设置元表函数
--第一个参数 子表
--第二个参数 元表
setmetatable(myTable,meat)
二、特定操作__tostring
当子表要被当做字符串使用时, 会默认调用这个元表中的__tostring
方法
示例代码:
meat = {
--当子表要被当做字符串使用时, 会默认调用这个元表中的__tostring方法
__tostring = function (t)
return t.name
end
}
myTable = {
name = "Lua"
}
setmetatable(myTable,meta)
print(myTable)
输出结果:
Lua
三、特定操作__call
当子表被当作一个函数来使用时, 会默认调用这个__call中的内容
meta = {
__call = function()
print("call方法")
end
}
myTable = {
name = "Lua"
}
setmetatable(myTable,meta)
myTable()
输出结果:
call方法
作为函数使用时,也可以往里面传入参数,但第一个参数默认是调用自己
meta = {
__tostring = function(t)
return t.name
end,
__call = function(a,b)
print(a)
print(b)
print("call方法")
end
}
myTable = {
name = "Lua"
}
setmetatable(myTable,meta)
myTable(1)
输出结果:
Lua
1
call方法
四、运算符重载
名称 | 关键字 |
---|---|
加法 | __add |
减法 | __sub |
乘法 | __mul |
除法 | __div |
取模 | __mod |
幂运算 | __pow |
等于 | __eq |
小于 | __lt |
小于等于 | __le |
示例:
meta4 = {
--相当于运算符重载 当子表使用+ 会调用该方法
-- +
__add = function (t1,t2)
return t1.age + t2.age
end,
-- -
__sub = function (t1,t2)
return t1.age - t2.age
end,
-- *
__mul = function (t1,t2)
return t1.age * t2.age
end,
-- /
__div = function (t1,t2)
return t1.age / t2.age
end,
-- %
__mod = function (t1,t2)
return t1.age % t2.age
end,
-- 幂运算
__pow = function (t1,t2)
return t1.age ^ t2.age
end,
-- ==
__eq = function (t1,t2)
return t1.age == t2.age
end,
-- <
__lt = function (t1,t2)
return t1.age < t2.age
end,
-- <=
__le = function (t1,t2)
return t1.age <= t2.age
end,
-- ..
__concat = function (t1,t2)
return t1.age .. t2.age
end
}
myTable4 = {age = 1}
setmetatable(myTable4,meta4)
myTable5 = {age = 2}
setmetatable(myTable5,meta4)
--myTable5不设置元表也能运行
print("+ : "..tostring(myTable4 + myTable5))
print("- : "..tostring(myTable4 - myTable5))
print("* : "..tostring(myTable4 * myTable5))
print("/ : "..tostring(myTable4 / myTable5))
print("% : "..tostring(myTable4 % myTable5))
print("^ : "..tostring(myTable4 ^ myTable5))
--如果要用条件运算符来比较连个对象
--这两个对象的元表一定要一致, 才能准确调用方法
print("== : "..tostring(myTable4 == myTable5))
print("< : "..tostring(myTable4 < myTable5))
print("<= : "..tostring(myTable4 <= myTable5))
print(".. : "..tostring(myTable4 .. myTable5))
输出结果:
+ : 3
- : -1
* : 2
/ : 0.5
% : 1
^ : 1
== : false
< : true
<= : true
.. : 12
五、__index
__index:当子表中找不到某一个属性时,会到元表中 __index指定的表去找索引
示例代码(若子表中不含age属性):
meta = {}
myTable = {}
-- __index的赋值,最好写到表外面初始化
meta.__index = {age = 1}
setmetatable(myTable,meta)
print(myTable.age)
输出:
1
上面myTable.age是在myTable中没有age属性的情况下,去访问元表中的__index
表;如果不想访问__index
的表,需要绕过它,则需用到另一个函数rawget(table,index)
meta = {
age = 1
}
myTable = {}
meta.__index = meta
setmetatable(myTable,meta)
print(myTable.age)
print(rawget(myTable,"age"))
输出结果:
1
nil
总结: 使用rawget
方法访问age
时,即使元表meta的__index
已经包含age
属性,也不会被访问到
六、__newindex
__newindex
:当赋值时,如果赋值一个不存在的索引,那么会把这个值赋值到__newindex
所指的表中, 不会修改自己
示例代码:
meta = {}
meta.__newindex = {}
myTable = {}
setmetatable(myTable,meta)
myTable.age = 1
print(myTable.age)
print(meta.__newindex.age)
输出结果:
nil
1
上面赋值时,是将值赋值到元表meta的__newindex
中,如果要将值赋值到myTable中,则需使用rawset(table,index,value)
示例代码:
meta = {}
meta.__newindex = {}
myTable = {}
setmetatable(myTable,meta)
rawset(myTable7,"age",2)
print(myTable.age)
输出结果:
2
总结: 使用rawset
方法赋值age
时,是直接将值赋到myTable,不会访问__newindex