lua 元表/元方法

在lua中,每个值都有其对应的操作,比如数值型有加减乘除等操作,字符串型有连接截取等操作,那么这些操作(加减乘除,连接截取等)定义在什么地方呢?定义在这些值默认的元表中,如果想修改这些操作(比如加法)就得修改其默认的元表,这样一来整型值所有的加法操作都被修改了。

table和userdata型没有默认元表,所以我们可以很容易修改其操作行为,比如对于table类型,我们是没有加法操作的,即两个table是不能够相加的,如果这时候想实现其相加操作怎么办呢,此时就可以为这两个table每一个设置一个元表,在其对应的元表中设置__add()函数, "__add" 是元表的键名(元表的键名也称之为事件(event),一般以 2 个下划线 "_" 开头), "__add" 函数是这个相加操作的元方法(metamethod)。对于值的操作,Lua 都将其关联上一个被称作事件的指定健,当 Lua 需要对一个值发起这些操作中的一个时, 它会去检查值的元表里是否有对应事件。如果有,则键名对应的值(元方法)将控制 Lua 怎样去执行这个操作,有人可能会有疑问,为什么相加操作用__add(),而不是其他,在此的解释是键名是固定写法,在lua中我们可以重定义的元方法有这些:


t1 = { "a" "b" "c" "d" }
t2 = { 5 6 7 8 9 }
 
mt = {}
mt.__add =  function (a, b)
     local tbl = {}
     local ret = {}
     for k, v in pairs(a)  do tbl[v] = true  end
     for k, v in pairs(b)  do tbl[v] = true  end
     for k, v in pairs(tbl)  do
         table.insert(ret, k)
     end
     return ret
end
 
setmetatable (t1, mt)
setmetatable (t2, mt)
 
t = t1 + t2
for k, v in pairs(t)  do print (v)  end

在执行加法操作时(t = t1 + t2), 首先检查该+运算符的两个table操作数的元表中是否有相加操作的元方法,如果没有则会报错,否则执行。

上述是对执行加法操作的元方法的举例,其他的操作类似。除此之外还有几个非常重要的元方法需要注意:__index,__newindex等。

__index用来对表进行访问:

当你通过键值对表进行访问的时候,如果该键没有值,则会查找对应的元表中是否存在该键对应的值,如果不存在则返回nil,否则返回__index对应的值。

Lua查找一个表元素时的规则,遵循如下3个步骤:

  • 1.在表中查找,如果找到,返回该元素,找不到则继续
  • 2.判断该表是否有元表,如果没有元表,返回nil,有元表则继续。
  • 3.判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值。

__newindex用于对表进行更新。

在对一个表中不存在的索引赋值时,不会直接把该值加到该表中,而是会把该值加入到该表的元表中。

mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })

print(mytable.key1)

mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)

mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)
以上输出结果为

value1
nil	新值2
新值1	nil
以上实例中表设置了元方法 __newindex,在对新索引键(newkey)赋值时(mytable.newkey = "新值2"),会调用元方法,而不进行赋值。而如果对已存在的索引键(key1),则会进行赋值,而不调用元方法 __newindex。

以上只是对lua元表元方法的简单总结,如果想详细了解其用法的可以参考以下这两篇文章,个人认为写的比较好,并且本文一部分内容是借鉴以下两位的:

http://www.runoob.com/lua/lua-metatables.html

http://dhq.me/lua-learning-notes-metatable-metamethod

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值