码迷,mamicode.com
首页 > 其他好文 > 详细

Lua 学习笔记(十一)元表与元方法

时间:2015-03-31 23:53:20      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:

     在Lua中的每个值都有一套预定义的操作集合。例如可以将数字相加,可以连接字符串,还可以在table中插入一对key-value等。但是我们无法将两个table相加,无法对函数作比较,也无法调用一个字符串。


     但是,Lua提供了元表与元方法来修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定的操作。例如,假设a和b都是table,通过元表可以定义如何计算表达式a+b。当Lua试图将两个table相加时,它会先检查两者之一是否有元表,然后检查该元表中是否有一个叫__add的字段。如果找到了该字段,就调用该字段对应的值。这个值也就是所谓的”元方法“,它应该是一个函数,用于计算table的和。
 
     Lua在创建一个新的table时不会创建元表。因此有两个函数可以获取与设置元表:
     setmetatable( t1,t2 ) 设置t1的元表为t2。
     getmetatable( t ) 获取t的元表。
 
     任何table都可以作为任何值的元表,而一组相关的table也可以共享一个通用的元表,此元表描述了它们共同的行为。一个table甚至可以作为它自己的元表,用于描述其特有的行为。总之,任何搭配形式都是合法的。
 
     在Lua中可以定义值的行为,那么就有相应的元方法:算术类的元方法、关系类的元方法、库定义的元方法以及table访问的元方法。
     1、算术类的元方法:__add(加)、__sub(减)、__mul(乘)、__div(除)、__unm(相反数)、__mod(取模)、__pow(乘幂)、__concat(连接操作符)
     2、关系类的元方法:__eq(等于)、__lt(小于)、__le(小于等于)
     3、库定于的元方法:__tostring(print时调用)、__metatable(设置后不可修改元表)
     4、table访问的元方法:__index(查询table)、__newindex(修改table的字段)
 
     在对table使用算术操作符时,Lua回去查找有没有操作符对应的元方法,如果有则调用算术类元方法,否则会产生错误信息。如 
 
table1 = { x=1 }
table2 = { x=2 }
print( table1 - table2 ) --产生错误:attempt to perform arithmetic on global ‘table1‘ (a table value)

 

 
如果设置了元表及元方法,就可以按照自己的意愿去处理(减法求值的例子):
 
技术分享
 
     关系类的元方法在使用上同算术类的元方法一样,都是在有操作符操作时去查询元方法,其中有三个关系操作符没有单独的元方法,Lua会把
     1、a~=b   转化为 not( a==b )
     2、a>b     转化为 b<a
     3、a>=b   转化为 b<=a
 
     库定义的元方法的应用:__tostring
 
技术分享
 
      库定义的元方法的应用:__metatable
 
技术分享
 
     table访问的元方法:__index。当访问一个table中不存在的字段时,得到的结果为nil。这是对的,但并非完全正确。实际上,这些访问会促使解释器去查找一个叫__index的元方法。如果没有这个元方法,那么访问结果就是nil,否则,就由这个元方法来提供最终的结果。
 
技术分享
 
table访问的元方法:__newindex。当对一个table中不存在的索引赋值时,解释器就会查找__newindex元方法。如果有这个元方法,解释器就调用它,而不是执行赋值。注意,Lua中有一个rawset(t,k,v)方法可以绕过元方法直接对table进行赋值。
 
技术分享
 
     通过table访问的元方法,__index、__newindex搭配使用可以很轻易的实现面向对象。元方法在元表中设置,只有当table被设置为元表时,table中的元方法才会有效。

Lua 学习笔记(十一)元表与元方法

标签:

原文地址:http://www.cnblogs.com/Richard-Core/p/4382290.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!