metatable用来为一个表重载一些默认的行为(运算和逻辑部分),metatable也是一个表,只是这个表被用来描述一些重载的操作符而已。因此metatable的域由两部分组成,
一部分是系统默认要求的保留域,另一部分是用户可以自己随意指定的自定义域。
metatable的默认元素:
算术运算方面:
__add 加法运算
__sub 减法运算
__mul 乘法运算
__div 除法运算
__unm 取负数运算
__pow 幂运算
关系运算方面:
__eq 等于关系运算
__lt
小于关系运算
__le 小于等于关系运算
关系运算不支持混合运算。混合运算的结果直接返回false
这里相等运算是个例外。如果比较的双发持有相同的metatable,则会去调用该metatable中对应的相等运算符
表自身运算方面:
ps: 表自身方面主要用来定义针对表的不存在域进行查询和修改和操作。
__index: 当查询表中不存在的元素时,如果该表的metatable中包含__index运算符,则返回该运算符的调用结果。
__newindex: 当向表中不存在的元素赋值时,如果该表的metatable中包含__newindex运算符,则返回该运算符的调用结果。
杂项运算方面:
__concat 表连接
系统库定义的运算符:
tostring():__tostring
如果表含有metatable,且metatable中包含__tostring域,则调用__tostring完成tostring的实际工作
setmetatable()/getmetatable(): __metatable
__metatable用来保护表的metatable
当一个表含有metatable,且metatable中包含__metatable时:
getmetatable()函数会返回该表的__metatable域而不是真正的metatable
setmetatable()函数则会直接出错,返回错误为 "cannot change protected metatable"
如此就达到了对一个表的metatable进行保护的目的(无法读取metatable,也无法更改metatable)
metatable虽然被lua的核心调用,但是究其本质也只是一个table。因此完全可以定义自己的原操作符,然后通过特定的函数进行封装调用,
上面"系统库定义的运算符"里面讲到的实现原理就是如此。
metatable的萌点还是相当多且给力的,-___-