lua学习笔记(八)
元表与元方法
基本概念
1.lua中每个值都有一个元表
2.table和userdata可以有各自独立的元表
3.其它类型的值共享其类型所属的单一元表
4.lua在创建新table时不会创建元表
5.其它基本类型的加减等操作都有预定义操作,table只能通过元表及元方法
6.getmetatable(t)获得table的元表
7.setmetatable(t, mt)设置table的元表为mt
8.t={} mt={} setmetatable(t,mt) assert(getmetatable(t)==mt)
9.任何table都可以作为任何值的元表,一组table可以共享同一个元表
10.一个table也可以作为自己的元表
11.在lua代码中只能设置table的元表,其它类型值的元表只能在C代码中设置
算术类元方法
__add(加法)对应"+"操作符
__sub(减法)对应"-"操作符
__mul(乘法)对应"*"操作符
__div(除法)对应"/"操作符
__unm(相反数) 对应一元"-"操作符
__mod(取模)对应"%"操作符
__pow(乘幂)对应"^"操作符
__concat(连接)对应".."操作符
__len(求长度)对应"#"操作符
先找第一个值的元方法,如果没有再找第二个值的元方法,都没有报错
关系类元方法
__eq(等于)
__lt(小于)
__le(小于等于)
没有大于和不等于元方法,但可以转化实现
a~=b转化为not(a==b)
a>b转化为b<a
a>=b转化为b<=a
库定义元方法
__tostring(字符串转换)
tostring函数会用此元方法进行转换
__metatable(指向元方法)
setmetatable、getmetatable会访问这个元方法
如果设置成其它内容就可以起到保护元表的功能
__mode(弱引用table模式)
它的值是一个字符串
如果包含"k"则表示table里的key是弱引用模式
如果包含"v"则表示table里的value是弱引用模式
table访问的元方法
可以改变table行为的方法
__index(访问表中不存在的字段)
当没有这个元方法时访问不存在字段会返回nil
当有元方法时两种访问形式
作为函数时有两个参数,第一个是被访问的table,第二个是不存在的key
作为table时就从这个table里找被访问的table里不存在的这个key
通常用于实现继承特性
作为函数的时候开销会大一些,但更灵活,可以实现多重继承和缓存等功能
如果不想涉及元方法,可以使用rawget(t,i)"原始访问",不会加速代码执行
__newindex(给表中不存在的字段赋值)
当没有这个元方法时会在被访问的table里创建新字段并赋值
当有元方法时两种访问形式
作为函数时有三个参数,第一个是被访问的table,第二个是不存在的key,第三个是value
作为table时,会在这个table里赋值而不是在被访问table里赋值
可以使用rawset(t,k,v)绕过元方法赋值
可以利用这两个元方法实现很多table的特殊功能
1.具有默认值的table,把带有值的table作为__index元方法
2.跟踪table的访问
t = {} --原table
local _t = t --私有化访问
t = {} --创建代码,名字相同
mt = {}
mt.__index = function(t,k)
print("access "..tostring(k))
return _t[k] --访问原来的table
end
mt.__newindex = function(t,k,v)
print("update "..tostring(k).." to "..tostring(v))
_t[k] = v --更新原来的table
end
setmetatable(t, mt)
但这个例无法遍历原来的table,pairs只能操作代理table
3.只读table,__index指向被访问table,__newindex弹错