lua 元表与元方法
元表
相关函数
# setmetatable(table,metatable): 为表设置元表
Sets the metatable for the given table. This function returns table.
If metatable is nil, removes the metatable of the given table.
If the original metatable has a __metatable field, raises an error.
* 为table设置元表metatable,返回设置后的表table
* 如果元表为nil,则会删除原先设置的元表
* 如果元表(metatable)中存在__metatable字段,setmetatable失败
* 注:5.4.4版本元表中含有__metatable字段,不会报错,可正常设置
# getmetatable(table): 获取指定表对象的元表
If object does not have a metatable, returns nil. Otherwise,
if the object's metatable has a __metatable field, returns the
associated value. Otherwise, returns the metatable of the given object
* 表对象没有元表,返回nil
* 如果表对象的元表有字段__metatable,返回字段对应的值
* 否则返回元表对象
示例:元表设置、获取
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
-- 表对象t、元表meta
> t={1,2,3,4,5,6}
> meta={}
-- 为t设置元表meta,设置后返回表对象t
> setmetatable(t,meta)
table: 0x600000314140
-- 获取t的元表
> getmetatable(t)
table: 0x600000310100
-- 遍历输出t
> for key,value in pairs(setmetatable(t,meta)) do print(key,value) end
1 1
2 2
3 3
4 4
5 5
6 6
-- 遍历输出meta
> for key,value in pairs(getmetatable(t)) do print(key,value) end
-- 设置元表:key='瓜田李下'
> meta.key='瓜田李下'
-- 遍历输出meta
> for key,value in pairs(getmetatable(t)) do print(key,value) end
key 瓜田李下
示例:元表含有__metatable字段
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> t={1,2,3,4,5,6}
> meta={__metatable='瓜田李下'}
-- 设置元表,可正常设置
> setmetatable(t,meta)
table: 0x60000029c8c0
-- 获取元表,返回元表__metatable字段对应的value
> getmetatable(t,meta)
瓜田李下
__index 元方法
__index:通过table[key]获取key在原来的表中不存在时使用
The indexing access operation table[key]. This event happens when
table is not a table or when key is not present in table. The metavalue
is looked up in the metatable of table.
* table不是表对象,或者不存在key时使用,会在元表中查找对应的key
The metavalue for this event can be either a function, a table, or
any value with an __index metavalue. If it is a function, it is called
with table and key as arguments, and the result of the call (adjusted
to one value) is the result of the operation. Otherwise, the final result
is the result of indexing this metavalue with key. This indexing is regular,
not raw, and therefore can trigger another __index metavalue.
* __index对应的value可以是table、function或者任何其他值
* 如果是函数,函数参数为表、key,函数返回一个值
示例:__index为表对象
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> t={1,2,3,4,5,6}
> meta={key='瓜田李下'}
> setmetatable(t,meta)
table: 0x6000006208c0
-- t.key不会直接读取元表中的同名key
> t.key
nil
-- 通过设置__index读取同名key
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> t={1,2,3,4,5,6}
> meta={key='瓜田李下'}
> setmetatable(t,meta)
table: 0x600001bc0180
> t.key
nil
> meta.__index={key='海贼王'}
> t.key
海贼王
示例:__index为函数
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> t={1,2,3,4,5,6}
> meta={key='瓜田李下'}
-- 设置元表
> setmetatable(t,meta)
table: 0x6000031c42c0
-- __index设置为匿名函数
> meta.__index=function(table,key) if(key=='key2') then return "海贼王" end end
-- 依次获取t.key、t.key2
> t.key
nil
> t.key2
海贼王
__newindex 元方法
__newindex:为table设置字段,table不是表对象、或者 不存在字段key时使用
The indexing assignment table[key] = value. Like the index event,
this event happens when table is not a table or when key is not
present in table. The metavalue is looked up in the metatable of table.
* 当table不是表对象,或者key不存在时使用
Like with indexing, the metavalue for this event can be either a
function, a table, or any value with an __newindex metavalue.
* __newindex的值可以是函数、表、或者其他任意值
If it is a function, it is called with table, key, and value as arguments.
Otherwise, Lua repeats the indexing assignment over this metavalue with the
same key and value. This assignment is regular, not raw, and therefore can
trigger another __newindex metavalue.
* 如果是函数,参数为table、key、value
* 如果不是函数,会直接在元表中设置新的值
Whenever a __newindex metavalue is invoked, Lua does not perform the primitive
assignment. If needed, the metamethod itself can call rawset to do the assignment
* 激活__newindex元方法时,lua不会进行对象分配,元方法自己会进行设置
示例:__newindex为表
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> t={1,2,3,4,5,6}
> metatable={}
-- 元表的__newindex为表metatable
> meta={__newindex=metatable}
> setmetatable(t,meta)
table: 0x600000004140
-- 获取t.key
> t.key
nil
-- 设置t.key
> t.key='瓜田李下'
-- 获取t.key
> t.key
nil
-- 获取metatable.key:新的key设置到元表字段中
> metatable.key
瓜田李下
示例:__newindex为函数,会在原来的表上添加key
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> t={1,2,3,4,5,6}
> metatable={}
-- __newindex为函数
> meta={__newindex=function(metatable,key,value) rawset(metatable,key,value) end}
-- 获取t.key
> t.key
nil
-- 设置t.key
> t.key='瓜田李下'
-- 获取t.key
> t.key
瓜田李下
-- 获取metatable.key:无返回值,
-- 设置为函数会在原来的表上添加key
> metatable.key
nil
__call 元方法
__call:调用非函数对象时触发
The call operation func(args). This event happens when Lua tries to call
a non-function value (that is, func is not a function). The metamethod is
looked up in func. If present, the metamethod is called with func as its
first argument, followed by the arguments of the original call (args).
* 当调用非函数对象时触发,第一个参数是当前对象,后面是传递个函数的参数
All results of the call are the results of the operation. This is the only
metamethod that allows multiple results
* 操作的结果就是调用的结果,这是唯一一个可以返回多个结果的元方法
示例
-- lua脚本:使用函数给表添加元素
huli@hudeMacBook-Pro lua % cat meta.lua
t={1,2,3,4,5,6}
setmetatable(t,{
__call=function(t,...)
local t2={...}
for key,value in pairs(t2) do
table.insert(t,value)
end
end})
t('瓜田李下','海贼王')
for key,value in pairs(t) do
print(key,value)
end
-- 运行脚本
huli@hudeMacBook-Pro lua % lua meta.lua
1 1
2 2
3 3
4 4
5 5
6 6
7 瓜田李下
8 海贼王
__tostring 元方法
__tostring:将对象转换为符串输出
Receives a value of any type and converts it to a string
in a human-readable format.
* 接收任意类型的数据,将其转换为可读的字符串
If the metatable of v has a __tostring field, then tostring
calls the corresponding value with v as argument, and uses
the result of the call as its result.
* 如果元表有字段__tostring,将相关数据作为参数,结果作为返回值
Otherwise, if the metatable of v has a __name field with a
string value, tostring may use that string in its final result.
* 如果元表有__name字段,对应的值为字符串类型,tostring可能注解将其作为返回值
示例:元表中有__name字段
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> t={1,2,3,4,5,6}
-- 元表中有__name字段
> meta={__name='瓜田李下'}
-- 设置元表
> setmetatable(t,meta)
瓜田李下: 0x600001084140
-- 输出表对象t
> t
瓜田李下: 0x600001084140
-- 删除元表
> setmetatable(t,nil)
table: 0x600001084140
示例:__tostring为函数
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> t={1,2,3,4,5,6}
-- __tostring为函数
> meta={__tostring=function() return '瓜田李下' end}
> t
table: 0x600001030140
-- 设置元表
> setmetatable(t,meta)
瓜田李下
> t
瓜田李下
示例:__tostring为函数,函数输出表元素,返回字符串
-- __tostring如果是函数,函数必须返回字符串,否则会报错
huli@hudeMacBook-Pro lua % cat meta2.lua
t={1,2,3,4,5,6}
meta={__tostring=function(table)
for key,value in pairs(table) do
print(key,value)
end
return '瓜田李下'
end
}
setmetatable(t,meta)
print(t)
-- 执行脚本
huli@hudeMacBook-Pro lua % lua meta2.lua
1 1
2 2
3 3
4 4
5 5
6 6
瓜田李下
操作符元方法
元方法
__add ==> '+'
__sub ==> '-'
__mul ==> '*'
__div ==> '/'
__mod ==> '%'
__unm ==> '-'
__eq ==> '=='
__lt ==> '<'.
__le ==> '<='
__concat ==> '..'
示例
-- 元表添加减操作
huli@hudeMacBook-Pro lua % cat meta3.lua
t={1,2,3,4,5,6}
meta={__sub=function(t1,t2)
local len=math.min(#t1,#t2)
for i=1,len do
t1[i]=t1[i]-t2[i]
end
return t1
end
}
setmetatable(t,meta)
t2={1,3,4,5,6,7,8}
for key,value in pairs(t-t2) do
print(key,value)
end
-- 执行脚本
huli@hudeMacBook-Pro lua % lua meta3.lua
1 0
2 -1
3 -1
4 -1
5 -1
6 -1