Lua学习与交流——元表的基础

关于Lua的元表,建议大家先读读Programming in Lua这本书里的讲解,我这里也对书里所讲的内容作一些总结。


一、什么是元表?
    元表(meta table)定义了一组方法(元方法),来改变一个表的行为。我把元表作为一个表的行为模式来理解。
    基本的操作如下:
    local Table = {}
    local mt = getmetatable(Table)-- Lua默认是没有为表创建元表的
   print(mt) -- ---> nil


二、有哪些元方法?
    按书本里的内容,元方法分为下面类:
    (注意,下面的方法都是元表的方法:比如 mt 是 Table的元表,则下面的方法就是mt.__xxx,而不是Table.__xxx)

    1. 第一类——算术运算相关的元方法:加减乘除。
        分别是 __add、__sub、__mul、__div。
        当两个表A,B作加、减、乘、除运算时,如:A + B,如果有相应的元方法,则会自动调用其中之一的元方法。哪具体调用哪一个表的元方法呢?A还是B?
        这里是Lua 选择元方法的原则: 
        1 、如果第一操作数拥有附带__add 域的元表,Lua 都将使用该元方法,而不管第二操作数为何; 
        2 、如果第一操作符不满足上述条件,而第二操作数却满足该条件,Lua 使用第二操作数的元方法; 
        3 、除此之外,Lua 将抛出错误。

        此外还有:__unm(负数操作符),__pow(指数操作符),__concat(连接操作符)

    2. 第二类——关系运算相关的元方法:
        分别是 __eq(等于)、__lt(小于)和__le (小于等于)。没有不等于、大于和大于等于
       这里要注意!!! 把 __le 和 __lt 的实现要分开。因为存在NaN(not a number),可能出现 a<=b, 但 b<a 二者同时成立。

    3. 第三类——库预定义的元方法:
       __tostring:在使用print的时候,Lua会自动去找该表(如果是一个table的话)对应的元表的__tostring。如果有,print打印出的就是该元方法的返回值。
       __metatable:可以通过这个方法为Table设置一个预设元表,比如 Table.mt.__metatable = "not your business",预设后,就不能通过setmetatable来设置元表了。

    4. 第四类——表存取操作的元方法:
      mt.__index当Lua 发现 表A 不存在某个域w(可理解成下标),但拥有一个附带 __index 域的元表时,Lua 将以 A(table 参数)和 w(缺少的域)作为参数调用__index 元方法,而该元方法将在原型中查找缺少的域并返回其对应的值。

           __index 元方法在继承中非常常见,因此Lua 提供了一套更便捷的方式。__index 不必非得是一个函数,它也可以是一个表。当它是一个函数时,Lua 将以表和缺少的域作为参数调用这个函数;而当它是一个表的时候,Lua 将在这个表中查找是否含有缺少的域。

      mt.__newindex:__newindex 元方法用于更新表,而__index 元方法则用于访问表。
           当你给表的一个缺失的域赋值,解释器就会查找__newindex 元方法:如果存在,则调用它,而不进行赋值操作。像__index 一样,如果元方法是一个表,解释器将对该表进行赋值操作,而不是原来的表。另外,有一个能直接存取的函数可以绕过元方法:执行rawset(t, k, v)将不会调用任何元方法,而是直接赋值v 给t 表的k 域。 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值