首页 > 代码库 > lua学习笔记(八)

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

lua学习笔记(八)