lua 字符串包含_lua元表(metatable)

相信你对 lua table已经十分熟悉了,元表是一个普通的table,普通到你可以像操作其他表一样随意的读写表中的数据。然而它又是特殊的,特殊到你可以利用它给表添加算术运算操作,不知道这些骚操作有没有勾起你一丝学习的欲望呢?
  • 元表的价值是如何体现的?

如果需要拿更高级的语言来理解lua,我们可以讲 元表就是lua语言的类,就像类定义了对象的行为一样,元表定义了以该表为元表的所有lua表的行为,也就是说lua元表中包含的k-v子表中都访问得到,不管这些k对应的是函数还是其他任何类型的数据。lua提供 setmetatable(tab, mt)全局函数将mt设置为tab的元表,提供 getmetatable(tab)全局函数获取tab的元表。
--- 【code】 1-1--- 定义表mt,mt中包含一个test方法和一个name变量local mt = {  name = "元表"}function mt:test()  print("this is a test function")end--- 定义一个tab,内容为空local tab = {}--- 让mt作为tab的元表setmetatable(tab, mt)--- 设置mt的__index元方法指向mt自己,这一步必不可少,后续会有介绍mt.__index = mt
以上代码中我们将 mt作为 tab的元表,按照OC或java来描述就是:我们将mt设置成了tab的类,tab是类mt的对象,因此tab不仅可以调用 test()方法,也可以访问 name变量。
print(tab.name)tab:test()--- 执行结果momo@MOMOdeMacBook-Pro Desktop $ lua mt.lua元表this is a test functionmomo@MOMOdeMacBook-Pro Desktop $
为了强化类和对象的概念,以后我们称元表为类,以某个表A为元表的表B为A对象(有点绕?)

setmetatable(tab, mt)就是设置tab为类mt的对象

getmetatable(tab)就是获取对象tab的所属类

要清楚的是:这里说的无论对象和类其本质都是一个lua表,就像OC中的对象和类本质都是结构体一样,只是类稍特殊一点而已,要不为啥它有个类对象的绰号呢。

通过这个例子我们可以得出一个结论:元表可以在两个表间实现类和对象的关系

  • 元方法是什么?

元方法(meta method)一些特殊的方法,一般以 __开头,比如上面提到的 __index,之所以用__开头,实际上是在告诉我们这些方法对外部是隐藏的,不需要开发者手动调用。它存在的意义是对表的`行为`进行控制,具体的行为包括 访问key新增k-v算术运算tostring结果等等。

比如给string添加加法运算:

--- 【code】 2-1--- 支持两个字符串执行+操作,如 "100" + "1"--- @return numberstring.__add = function(s, num)    local a = tonumber(s) or 0    local b = tonumber(num) or 0    return a + bendlocal result = "100" + "200"print(type(result), result)  -- > number  300.0

其他还有很多感兴趣的话可以自行搜索一下。

通过这个例子相信你已经对元方的作用有了些自己的体会。

  • 十分重要的元方法`__index` 和 `__newindex`

__index控制着表的读权限,__newindex控制着表的写权限。

默认情况下__index和__newindex都指向nil,如需对表进行访问控制,则需要实现__index和__newindex的指向。

__index是如何影响对象访问类中各个key的:

按照code 1-1的代码来讲tab是怎样访问到mt的name字段的分析:1. tab中不包含name字段2. mt是tab的元表3. mt的__index指向mt自己tab.name的访问顺序:1. 若tab中有name则返回,否则转向mt2. 访问mt的__index,若没有__index指向则返回nil,   若__index指向一个表,则访问该表中的name字段
若对象访问一个自身不存在的key,则访问类(元表)的__index指向,因为一般情况下__index指向类(元表)自己,因此是在类(元表)中尝试访问该key。如果类(元表)中也不存在这个key呢?如果类(元表)也拥有父类(元表),则尝试访问其父类(元表)的__index,以此类推。是不是有点继承的意思呢?

__index指向一个function

对象访问一个key的操作实际上有两个参数,一个是对象,另一个是key。因此如果__index指向一个函数,例如:
mt = {    __index = function(obj, key)         -- do something        return value    end}
__index指向的函数是有两个参数的,第一个是要访问的表,第二个是要访问的key,当__index指向function时将会执行这function,并返回其return的结果。 使用__index指向function可以对类的某些字段进行访问控制

可能存在一种需求:撇开对元表的访问,直接返回该table是否拥有某些值该怎么办?

这个时候我们就需要将__index指向一个function,当然这还不够,lua还提供了一个避免访问元表的访问方式 rawget(tab, key)
mt = {    __index = function(obj, key)         -- 返回obj中key对应的值,若obj中不存在key对应的记录则返回nil,否则返回对应的值        -- 若此处使用return obj[key]则会造成死循环        return rawget(obj, key)    end}

__newindex是如何影响对像存值的

对象是个lua表,可以随意在其中保存字段。
按照code 1-1的代码来讲是怎样给tab写入name字段的例如:tab.name = "momo"分析:1. tab中不存在name字段2. tab有元表mt3. mt中无__newindex指向代码tab.name = "momo"的访问顺序1. tab中有name字段则直接在tab中添加键值,操作完成,否则步骤22. 访问tab的元表mt,若无则直接在tab中添加键值,操作完成,否则步骤33. 访问tab的__newindex指向,若无直接在tab中添加键值,否则步骤44. 若__newindex指向一个表,则在该表中写入键值;若指向一个function,则执行该function
对标的写操作涉及到三个参数,分别是:被操作表、key、value。

即__newindex对应的函数有三个参数:

mt = {    __newindex = function(obj, key, value)        -- 同rawset(obj, key),rawset方法将摒弃元表的影响,直接向表obj中写入键值        -- 若此处使用obj[key] = value将造成死循环        rawset(obj, key, value)    -- 无需返回值}

__newindex使用较少,一般在有对表写入访问控制的情况下才用


以上 ~

写在最后:其实只要付出了还是会有回报的,它可能会迟到但绝不会缺席。

0e46758524be6e5dfab80cb8bef68595.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值