Lua Metatable

作者: 小城大麦 | 来源:发表于2016-08-16 17:30 被阅读25次

    算数运算和逻辑运算(类似操作符重载)

    +-*/ __add __sub __mul __div
    % ^ __mod,__pow
    == < > __eq __lt __le
    
    local obj = {1}
    m = getmetatable(obj)
    print m -- nil
    m = {__add = function(a,b) return {a,b} end}
    setmetatable(obj,m)
    local obj2 = {2}
    setmetatable(obj2,m)
    local ret = obj +_ obj2 -- {{1},{2}}
    

    库定义的元方法

    __tostring 格式输出
    local a = {}
    local mt = {__tostring = function(t) return "table_a" end}
    setmetatable(a,mt)
    print() -- print(tostring(a)) == __tostring(a) table_a
    
    __metatable:如果有值,getmetatable返回此值,且
    不能调用setmetatble修改
    

    table访问的元方法
    __index 如果访问table中字段不存在,且存在__index的元方法,那么调用__index [__index(table,key)]
    使用rawget(table,key)方法可以绕过这个机制

    local obj = {name="obj"}
    local mt = {
      __index = function(t,k) return "test" end
    }
    setmetatable(obj,mt)
    -- any not exists key in obj will return test
    print(obj.name) -- "obj"
    print(obj.any) -- "test"
    

    __newindex 如果更新的字段在table不存在,且存在__newindex元方法,那么将调用__newindex方法[__newindex(table,key,value)]
    使用rawset(table,key,value)方法可以绕过这个机制

    obj = {name="obj"}
    mt = {
        -- we cannot use t[k]=v this will recursive invoke __newindex
      __newindex = function(t,k,v) v = "test_"..tostring(v) rawset(t,k,v) end
    }
    
    setmetatable(obj,mt)
    print(obj.name) -- "obj"
    obj.name = "hello" print(obj.name) -- "hello"
    obj.any = "work" print(obj.any) -- "test_work"
    obj.any = "any" print(obj.any) -- "any" because any is exists in table
    

    应用代理访问

    function create_proxy(target)
        local _t = target
        local t = {}
        local mt = {
            __index = function(t,k) print("access to element "..tostring(k)) return _t[k] end,
            __newindex = function(t,k,v) print("update element "..tostring(k)) _t[k] = v end
        }
        setmetatable(t,mt)
        return t;
    end
    target = {}
    proxy = create_proxy(target)
    proxy.price = 10.0
    print(proxy.price)
    

    get/set一种简单实现

    local Book = {}
    function Book.new()
      local accessor = {
        name = {
          value = 0,
          get = function() return value end,
          set = function(new_value) value = new_value end
        }
      }
      local meta = {
        __index = function(_,key)
            return accessor[key].get();
          end,
        __newindex = function(_,key,value)
              accessor[key].set(value)
          end
      }
      local o = {}
      setmetatable(o,meta);
      return o
    end
    
    local mybook = Book.new()
    mybook.name = "bookname_100"
    print(mybook.name)
    

    readOnly

    function readOnly(t)
        local proxy = {}
        local mt = {
            __index = t,
            __newindex = function(t,k,v) error("attempt to update a readonly table",2) end
        }
        setmetatable(proxy,mt)
        return proxy
    end
    

    弱应用与垃圾回收
    Lua中table的弱引用有三种Key弱引用,Value弱应用,Key,Value同时为弱引用
    对应字符串,其本身是一个值,不是对象,并不一定会被回收。

    定义一个弱引用 __mode元字段

    a = {}
    mt = {__mode = "k"}
    setmetatable(a,mt) -- a为key的弱引用
    key = {}
    a[key] = 1
    key={} //pre key is nil,will be collected as garbage
    a[key] = 2
    collectgarbage()
    for k,v in pairs(a) do print(v) end -->2
    

    相关文章

      网友评论

        本文标题:Lua Metatable

        本文链接:https://www.haomeiwen.com/subject/rpbpsttx.html