LUA-1 Table中的Metatables和Metamethods

table是lua中的唯一的一个数据结构.而且,table中的数据可以是任意类型的,当然也可以是函数类型.

例如:

a = {};-->声明一个table

a[1] = function() print("a"); end; -->这样就给a[1]赋予了一个函数.

也就是说,table里可以存储各种各样的东西.

同时如果

a[2] = a;-->这也是可行的,但是注意,lua中的这种赋值用法得到的结果其实是: a[2]是a的引用,而并非把a的内容都复制给a[2].

也就是说,一个table中既可以有数据,也可以有函数.

而Metatables(元表)其实也是一个table,只不过有一些特别的性质.我们可以通过getmetatable(a)来获得a的元表,但是此时获得的值是nil,因为

lua默认新的table是不包含元表的.因此我们需要先设置一个元表,通过setmetatable()函数.

首先我们要声明一个元表:

mt = {};-->声明一个表,任何一个表都可以作为元表

setmetatable(a,mt);-->将元表设置到a表中,给a设置元表其实是添加了一个mt的引用

mt[1] = 90;-->可以给元表添加一些值,注意:无论在什么时候添加值,都会影响所有的以这个表作为元表的表(例如a表).

mt.__add = function(a,b)...end;

最后的这条代码需要特别说明,__add是元表的特有的函数,即Metamethods(元函数).

例如c = a + b,如果a和b是表,那么lua会先检测a表,看看元表中有没有__add函数,如果有,就调用这个函数来处理两个表的加法操作,并将返回值赋值给c.如果没有的话,就会调用b的的元表的__add函数,如果两个表都没有这个函数的话,那么lua就会报错!

同样还有下面这些Metamethods(元函数):

__mul(乘*),__sub(减-),__div(除/),__unm(负-),__pow(幂^),__concat(连接..)等元函数(括号内为操作符说明).

还有比较运算:

__eq(等于==),__lt(小于<),__le(小于等于<=),之所以只有三个,是因为其他的比较都可以转换为这三种,例如a>b可以转换成not(a <= b);

上面的乘除和比较因为必须要有两个参数,所以函数的形参都是 __xxx(a,b)这种形式,当然__unm(a)只要一个形参就够了

还有库函数运算:

__tostring(转换成字符串);-->当我们print(a);的时候就会调用a的tostring函数,也就是元表中的__tostring函数.

还有关于表的查找:

__index(t,key)-->当调用a["x"]的时候就会调用这个函数t为表,key为下标.

__newindex(t,k)-->当给一个表中本不存在的变量赋值的时候,就会调用这儿函数.

-->还要注意一点,如果使用rawset(t,key)和rawget(t,key)函数来创建和访问表中的数据的话,是不会调用元函数的!

 

 

 

 

 

 

posted @ 2012-08-05 13:49  Kinel  阅读(351)  评论(0)    收藏  举报