Lua进阶学习:元表

元表的介绍

在 Lua table 中我们可以访问对应的 key 来得到 value 值,但是却无法对两个 table 进行操作(比如相加)。因此 Lua 提供了元表(Metatable),允许我们改变 table 的行为,每个行为关联了对应的元方法。例如,使用元表我们可以定义 Lua 如何计算两个 table 的相加操作 a+b。当 Lua 试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫 __add 的字段,若找到,则调用对应的值。 __add 等即时字段,其对应的值(往往是一个函数或是 table)就是"元方法"


设置元表

setmetatable(table,metatable): 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。
getmetatable(table): 返回对象的元表(metatable)。

-- 设置方式 1
mytable = {} -- 普通表
mymetatable = {} -- 元表
setmetatable(mytable, mymetatable) -- 把 mymetatable 设为 mytable 的元表

-- 设置方式 2
mytable2 = setmetatable({}, {})
--此时元表为匿名状态,想要获取需要使用 
print(getmetatable(mytable2)) -- > table

元方法

__tostring 和 __call 重载

__tostring 当被当做字符串使用时,调用__tostring
__call 当子表被当作一个函数使用时,调用__call

-- __tostring 和 __call
meta = {
    -- 当被当做字符串使用时,调用__tostring
    __tostring = function(t) -- 默认把自己当第一个参数传进来
        return t.str
        -- return "mmm" 
    end,
    -- 当子表被当作一个函数使用时,调用__call
    __call = function(a, b)
        print("hello", a, b) -- a 还是自己本身,b才是传的参数
    end
}
table = {str = "nnn"}
setmetatable(table, meta)
print(table) -- > 此时table被当成 string   nnn
table("123"); -- > 此时table被当成 function hello nnn 123

输出结果
在这里插入图片描述

__add等运算符重载

运算符重载 当把表进行对应的计算时可以重写运算函数

模式描述
__add对应的运算符 ‘+’.
__sub对应的运算符 ‘-’.
__mul对应的运算符 ‘*’.
__div对应的运算符 ‘/’.
__mod对应的运算符 ‘%’.
__unm对应的运算符 ‘-’.
__concat对应的运算符 ‘…’.
__eq对应的运算符 ‘==’.
__lt对应的运算符 ‘<’.
__le对应的运算符 ‘<=’.

使用示例: + - ==

-- 运算符重载 当把表进行对应的计算时可以重写运算函数
meta2 = {
    __add = function(a, b)
    	 return a.age + b.age 
    end,
    __sub = function(a, b) 
    	return a.age - b.age 
    end,
    __eq = function(a, b) 
    	return a.age == b.age 
    end
}
tableA = {age = 1}
setmetatable(tableA, meta2)
tableB = {age = 3}

print(tableA + tableB) -- > 4
print(tableA - tableB) -- > -2
print(tableA == tableB) -- > true

输出结果
在这里插入图片描述

__index 和 _newindex

__index 当找不到对应属性时 找元表设置的__index所指向的表
rawget() 忽略__index

meta3 = {}
table3 = {}
table4 = {age = 3}
setmetatable(table3, meta3)

print(table3.age) -- > nil 
meta3.__index = {age = 4} -- 设置 __index
print(table3.age) -- > 4 
meta3.__index = table4 -- 设置 __index表为 table4
print(table3.age) -- > 3 
print(rawget(table3, "age")) -- > nil 

-- __index 还可以套用
meta4 = {name = "111"}
meta4.__index = meta4
setmetatable(table4, meta4)
print(table3.name) -- > 111  

输出结果
在这里插入图片描述

__newindex 当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作
rawset() 忽略__newindex

meta5 = {}
meta5.__newindex = {}
table5 = {}
setmetatable(table5, meta5)
table5.age = 1 -- 实际上这时改掉的时 元表 __newindex 里的age
print(table5.age) -- > nil 
print(meta5.__newindex.age) -- > 1 

-- 使用rawset() 就不会设置到__newindex上去了
rawset(table5, "age", 2)
print(table5.age) -- > 2
-- __newindex也是一层层往上找

输出结果
在这里插入图片描述

其他元方法

模式描述
__idivthe floor division (//) operation. Behavior similar to the addition operation.
__bandthe bitwise AND (&) operation. Behavior similar to the addition operation, except that Lua will try a metamethod if any operand is neither an integer nor a float coercible to an integer (see §3.4.3)
__borthe bitwise OR (
__bxorthe bitwise exclusive OR (binary ~) operation. Behavior similar to the bitwise AND operation.
__bnotthe bitwise NOT (unary ~) operation. Behavior similar to the bitwise AND operation.
__shlthe bitwise left shift (<<) operation. Behavior similar to the bitwise AND operation.
__shrthe bitwise right shift (>>) operation. Behavior similar to the bitwise AND operation.
__lenthe length () operation. If the object is not a string, Lua will try its metamethod. If there is a metamethod, Lua calls it with the object as argument, and the result of the call (always adjusted to one value) is the result of the operation. If there is no metamethod but the object is a table, then Lua uses the table length operation (see §3.4.7). Otherwise, Lua raises an error. #

END

参考链接 http://www.lua.org/manual/5.4/manual.html
参考链接 https://www.runoob.com/lua/lua-metatables.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

又来077

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值