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弹错