lua元表

2018-05-11 13:32:50

lua元表其实就是为了扩展表格间的运算,比如之前我们如果让2个表格相加就会报错,一旦我们设置了元表并加上了__add属性,那么就会正常执行。

先看2个元表相关的函数

setmetatable(table,metatable)

将metatable设置为table的元表并返回table,如果metatable为nil,则删除table的元表。
如果table的元表里面存在__metatable则报错。


getmetatable(obj)

如果obj没有设置元表,返回nil,如果obj的元表里面有__metatable属性,则返回对应的值。
否则返回obj的元表

__metatable这个元表属性是用来起保护作用的,请看如下例子

local ta = {}

local tb = {__metatable = '沧浪水'}

--把tb设置成ta的元表并返回ta
setmetatable(ta,tb)
--注意由于tb中有__metatable属性,所以会保护ta的元表
--接下来对ta的元表做的所有修改操作都将报错
--试图读取ta的元表的直接返回__metatable对应的值

--试图删除ta的元表
--报错 cannot change a protected metatable
setmetatable(ta,nil)

-- 读取ta的元表
-- 直接返回 沧浪水
local res = getmetatable(ta)


__index元方法

比较常用,当我们通过键名去访问一个ta表格时,如果不存在这个键,lua还会尝试搜索ta的元表的__index,没有则返回nil
1.如果__index对应的是表格,直接搜索键名,搜索不到返回nil
2.如果__index所对应的是函数,则调用函数并传递ta和键名参数

例子

local ta = {}
ta['name_url'] = 'http://www.freecls.com'

--nil
print(ta.name)

local tb = {}
tb.__index = {name='沧浪水'}

setmetatable(ta,tb)

--沧浪水
print(ta.name)

--改成函数
tb.__index = function(ta,key)
    return ta[key..'_url']
end

--http://www.freecls.com
print(ta.name)


__newindex元方法

当对表格ta设置新值时,会查找ta的元表中是否有__newindex属性,如果存在,则ta赋值,把值赋给__newindex对应的表格

例子

local ta = {}
ta['name_url'] = 'http://www.freecls.com'

local tc = {}

local tb = {}
tb.__newindex = tc

setmetatable(ta,tb)

ta.name = '沧浪水'

print(ta.name)      --nil
print(tc.name)      --沧浪水


运算元方法

__add 对应的运算符 '+'
__sub 对应的运算符 '-'
__mul 对应的运算符 '*'
__div 对应的运算符 '/'
__mod 对应的运算符 '%'
__unm 对应的运算符 '-'
__concat 对应的运算符 '..'
__eq 对应的运算符 '=='
__lt 对应的运算符 '<'
__le 对应的运算符 '<='

在这里我只挑一个进行讲解,读者应该可以举一反三

假设我们想实现一个功能,就是2个表格用..操作时,把2个表格的内容合并返回

例子

local ta = {}
ta['url'] = 'http://www.freecls.com'

local tb = {}
tb.__concat = function(ta1,ta2)
    local ta = {}
    for k,v in pairs(ta1) do
        ta[k] = v
    end
    
    for k,v in pairs(ta2) do
        ta[k] = v
    end
    
    return ta
end

--设置元表
setmetatable(ta,tb)


local tc = {1,name='沧浪水',age='28',2}

--将会调用元方法__concat并传入ta,tc作为参数
local res = ta..tc

for k,v in pairs(res) do
    print(k,v)
end

--[[
1	1
2	2
url	http://www.freecls.com
name	沧浪水
age	28
--]]


__call元方法

设置了这个元方法,表格可以当做函数来使用

例子

local ta = setmetatable({'http://www.freecls.com'},{
    __call = function(ta1,str)
        print(#ta1)
        print('hello '..str)
    end
})

ta('freecls')

--[[
1
hello freecls
--]]


__tostring元方法

设置了这个元方法,可以改变表格的输出行为,默认的情况下会输出表格的内存地址

例子

local ta = {'hello', 'http://www.freecls.com'}

--table: 0x1943700
print(ta)

local ta = setmetatable(ta,{
    __tostring = function(ta)
        local str = ''
        for k,v in pairs(ta) do
            str = str..k..' '..v..'\n'
        end
        
        return str
    end
})

print(ta)

--[[
1 hello
2 http://www.freecls.com

--]]


总结

1.本文只是对lua元表做简单的介绍,如果有疑问可以给我留言
2.lua的版本为5.1,运行环境centos7 64位
3.原文地址http://www.freecls.com/a/2712/1a

©著作权归作者所有
收藏
推荐阅读
  • lua模块编写

    lua允许我们编写自定义模块以便后面调用,在编写模块之前我们先认识2个知识点1.lua语言中数组,模块其实都是table表格。2.在之前的lua基本语法里我们知道函数是可以赋值给变量的好,我们新建一个...

  • lua基本语法

    变量1.变量无需声明2.变量没声明为nil,赋值为nil等同于删除3.lua把nil,false视为假,其他都为true4.Lua 中的变量全是全局变量,那怕是语句块或是函数里,除非用 local 显...

  • lua基础函数 type,tonumber,tostring,pcall,print

    type(v)用来判断v的类型返回字符串"nil", "number", "string", "boolean", "table", "function", "thread", "userdata"t...

  • lua ipairs pairs

    这两个函数都是用来遍历表格数组的,性能几乎没有区别,其他区别如下:iparis只会遍历数字索引,并在遇到第一个非数字索引时终止paris则会遍历所有例子 &nbsp;local t = {22,33,...

  • lua 基本函数dofile loadfile loadstring

    dofile([filename])如果提供了filename则打开读取里面内容并以代码块方式执行,没提供则从标准输入stdin读取并执行。如果报错,错误会上传到到调用者(运行在非保护模式)例子新建a...

  • nginx模块 ngx_http_headers_module

    ngx_http_headers_module 模块是用来增加 Expires 和 Cache-control,或者是任意的响应头。Syntax: add_header name value [alw...

  • nginx模块 ngx_http_gunzip_module、ngx_http_gzip_module、ngx_http_gzip_static_module

    ngx_http_gunzip_module 模块将文件解压缩后并在响应头加上 "Content-Encoding: gzip" 返回给客户端。为了解决客户端不支持gzip压缩。编译的时候带上 --w...

  • nginx模块 ngx_http_flv_module、ngx_http_mp4_module

    ngx_http_flv_module模块提供了对 flv 视频的伪流支持。编译的时候带上 --with-http_flv_module。它会根据指定的 start 参数来指定跳过多少字节,并在返回数...

  • nginx模块 ngx_http_fastcgi_module

    ngx_http_fastcgi_module 模块使得nginx可以与 fastcgi 服务器通信。比如目前要使得 nginx 支持 php 就得使用 fastcgi技术,在服务器上装上 nginx...

  • nginx模块 ngx_http_autoindex_module

    ngx_http_autoindex_module 模块可以将uri以 / 结尾时,列出里面的文件和目录。Syntax: autoindex on | off; Default: autoindex ...

简介
天降大任于斯人也,必先苦其心志。