lua 元表与元方法


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

      

            

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值