元表元方法
lua中每个值都可以拥有元表(但不一定有)。元表也是普通表,只是用来记录数据在某些特定条件下的操作行为。如: 对表进行相加操作时,lua会判断是否存在__add
的元方法,并对其进行调用。可以通过setmetatable(table,metatable)
的方式设置元表。通过getmetatable(table)
获取元表。
1 | -- 两个表相加 |
数学计算相关部分元方法的key如下:
1 | __add: +(加) __sub: -(减) __mul: x(乘) |
注意
- 如果两个表具有相同的元方法,那在执行此计算时没有问题。
- 如果两个表具有不同的元方法:
- 第一个值有元表,以第一个为准
- 第一个没,第二个有元表,以第二个为准
- 都没有:无法计算,报错
一些特殊的元方法
__tostring
用来修改表的输出行为。
1 | t = {200,300,400} |
__index
**–>用于查询访问<–**。当通过key
访问表中数据时,如果表中这个key是没有值的,那么在__index
元方法存在时就会访问元方法。
- 如果
__index
元方法是一张表。就会从这张表中取数据1
2
3
4
5
6
7t = {name = "tom"}
setmetatable(t, {__index = { name = "default", age = 0 }})
print(t.name)
print(t.age)
--> tom
--> 0 - 如果
__index
元方法是一个function。那么就会调用此方法。1
2
3
4
5
6
7
8t = {}
setmetatable(t, {__index = function(table, key)
print("表中不存在key:"..key)
end})
print(t.count)
--> 表中不存在key:count
--> nil
__newindex
**–>用于更新修改<–**。当对一个当前不存在的key赋值时,如果存在__newindex
元方法,会调用此元方法而不是直接赋值。同样__newindex
可以是方法也可以是一个表。
是一个方法。
1
2
3
4
5
6
7
8
9
10
11t = {k1 = "Tom"}
setmetatable(t, {__newindex = function(_table, k, v)
print("请不要尝试给"..k.."赋值")
end})
print(t.k1)
t.k2 = "Kitty"
print(t.k2)
--> Tom
--> 请不要尝试给k2赋值
--> nil如果是表。添加的数据会添加在元方法的表中(如下的mt中),而不是t中。
1
2
3
4
5
6
7
8
9
10
11t = {k1 = "Tom"}
mt = {}
setmetatable(t, {__newindex = mt})
print(t.k1)
t.k2 = "Kitty"
print(t.k2)
print(mt.k2)
--> Tom
--> nil
--> Kitty
忽略元表
当我们需要忽略__index
和__newindex
时。
- 可以通过
rawget
函数忽略__index元方法,存粹的调用表中的值。使用rawset
函数忽略__newindex元方法,纯粹的给表赋值。1
2
3
4
5
6
7
8
9
10
11t = {name = "Tom"}
mt1 = {age = 0}
mt2 = function(t, k, v) print("不许赋值!") end
setmetatable(t, {__index = mt1 ,__newindex = mt2})
print(rawget(t, "age"))
rawset(t, "age", 999)
print(t.age)
--> nil
--> 999
一个出自网络的例子
1 | local smartMan={name="none"} |
__call
把表当作方法调用时会被调用。
1 | t = {} |