现在的位置: 首页 > 综合 > 正文

Lua的默认metamethod列表

2013年10月28日 ⁄ 综合 ⁄ 共 4349字 ⁄ 字号 评论关闭

metamethod
"add": + 操作。
下面这个 getbinhandler 函数定义了 Lua 怎样选择一个处理器来作二元操作。 首先,Lua 尝试第一个操作数。 如果这个东西的类型没有定义这个操作的处理器,然后 Lua 会尝试第二个操作数。

     function getbinhandler (op1, op2, event)
       return metatable(op1)[event] or metatable(op2)[event]
     end
通过这个函数, op1 + op2 的行为就是

     function add_event (op1, op2)
       local o1, o2 = tonumber(op1), tonumber(op2)
       if o1 and o2 then  -- 两个操作数都是数字?
         return o1 + o2   -- 这里的 '+' 是原生的 'add'
       else  -- 至少一个操作数不是数字时
         local h = getbinhandler(op1, op2, "__add")
         if h then
           -- 以两个操作数来调用处理器
           return h(op1, op2)
         else  -- 没有处理器:缺省行为
           error(···)
         end
       end
     end
"sub": - 操作。 其行为类似于 "add" 操作。
"mul": * 操作。 其行为类似于 "add" 操作。
"div": / 操作。 其行为类似于 "add" 操作。
"mod": % 操作。 其行为类似于 "add" 操作, 它的原生操作是这样的 o1 - floor(o1/o2)*o2
"pow": ^ (幂)操作。 其行为类似于 "add" 操作, 它的原生操作是调用 pow 函数(通过 C math 库)。
"unm": 一元 - 操作。
     function unm_event (op)
       local o = tonumber(op)
       if o then  -- 操作数是数字?
         return -o  -- 这里的 '-' 是一个原生的 'unm'
       else  -- 操作数不是数字。
         -- 尝试从操作数中得到处理器
         local h = metatable(op).__unm
         if h then
           -- 以操作数为参数调用处理器
           return h(op)
         else  -- 没有处理器:缺省行为
           error(···)
         end
       end
     end
"concat": .. (连接)操作,
     function concat_event (op1, op2)
       if (type(op1) == "string" or type(op1) == "number") and
          (type(op2) == "string" or type(op2) == "number") then
         return op1 .. op2  -- 原生字符串连接
       else
         local h = getbinhandler(op1, op2, "__concat")
         if h then
           return h(op1, op2)
         else
           error(···)
         end
       end
     end
"len": # 操作。
     function len_event (op)
       if type(op) == "string" then
         return strlen(op)         -- 原生的取字符串长度
       elseif type(op) == "table" then
         return #op                -- 原生的取 table 长度
       else
         local h = metatable(op).__len
         if h then
           -- 调用操作数的处理器
           return h(op)
         else  -- 没有处理器:缺省行为
           error(···)
         end
       end
     end
关于 table 的长度参见 §2.5.5 。

"eq": == 操作。 函数 getcomphandler 定义了 Lua 怎样选择一个处理器来作比较操作。 元方法仅仅在参于比较的两个对象类型相同且有对应操作相同的元方法时才起效。
     function getcomphandler (op1, op2, event)
       if type(op1) ~= type(op2) then return nil end
       local mm1 = metatable(op1)[event]
       local mm2 = metatable(op2)[event]
       if mm1 == mm2 then return mm1 else return nil end
     end
"eq" 事件按如下方式定义:

     function eq_event (op1, op2)
       if type(op1) ~= type(op2) then  -- 不同的类型?
         return false   -- 不同的对象
       end
       if op1 == op2 then   -- 原生的相等比较结果?
         return true   -- 对象相等
       end
       -- 尝试使用元方法
       local h = getcomphandler(op1, op2, "__eq")
       if h then
         return h(op1, op2)
       else
         return false
       end
     end
a ~= b 等价于 not (a == b) 。

"lt": < 操作。
     function lt_event (op1, op2)
       if type(op1) == "number" and type(op2) == "number" then
         return op1 < op2   -- 数字比较
       elseif type(op1) == "string" and type(op2) == "string" then
         return op1 < op2   -- 字符串按逐字符比较
       else
         local h = getcomphandler(op1, op2, "__lt")
         if h then
           return h(op1, op2)
         else
           error(···);
         end
       end
     end
a > b 等价于 b < a.

"le": <= 操作。
     function le_event (op1, op2)
       if type(op1) == "number" and type(op2) == "number" then
         return op1 <= op2   -- 数字比较
       elseif type(op1) == "string" and type(op2) == "string" then
         return op1 <= op2   -- 字符串按逐字符比较
       else
         local h = getcomphandler(op1, op2, "__le")
         if h then
           return h(op1, op2)
         else
           h = getcomphandler(op1, op2, "__lt")
           if h then
             return not h(op2, op1)
           else
             error(···);
           end
         end
       end
     end
a >= b 等价于 b <= a 。 注意,如果元方法 "le" 没有提供,Lua 就尝试 "lt" , 它假定 a <= b 等价于 not (b < a) 。

"index": 取下标操作用于访问 table[key] 。
     function gettable_event (table, key)
       local h
       if type(table) == "table" then
         local v = rawget(table, key)
         if v ~= nil then return v end
         h = metatable(table).__index
         if h == nil then return nil end
       else
         h = metatable(table).__index
         if h == nil then
           error(···);
         end
       end
       if type(h) == "function" then
         return h(table, key)      -- 调用处理器
       else return h[key]          -- 或是重复上述操作
       end
     end
"newindex": 赋值给指定下标 table[key] = value 。
     function settable_event (table, key, value)
       local h
       if type(table) == "table" then
         local v = rawget(table, key)
         if v ~= nil then rawset(table, key, value); return end
         h = metatable(table).__newindex
         if h == nil then rawset(table, key, value); return end
       else
         h = metatable(table).__newindex
         if h == nil then
           error(···);
         end
       end
       if type(h) == "function" then
         return h(table, key,value)    -- 调用处理器
       else h[key] = value             -- 或是重复上述操作
       end
     end
"call": 当 Lua 调用一个值时调用。
     function function_event (func, ...)
       if type(func) == "function" then
         return func(...)   -- 原生的调用
       else
         local h = metatable(func).__call
         if h then
           return h(func, ...)
         else
           error(···)
         end
       end
     end
 
__mode 域中是一个包含有字符 'k' 的字符串时, table 的键就是 weak 的。 如果 __mode 域中是一个包含有字符 'v' 的字符串时, table 的值就是 weak 的。
__tostring 获取对象的字符串描述
__gc 在gc回收前的调用,相当于析构。如果没有则直接回收了

抱歉!评论已关闭.