Lua元表和元方法「DaemonCoder」 lua table中元素数量
liebian365 2024-10-29 15:54 26 浏览 0 评论
什么是元表和元方法
Lua里定义一个表,都会有一个和这个表对应的元表,元表也是一个表,不过元表中定义了对之对应的表的一些特殊操作。比如一个取表中的某一个字段时,如果字段不存在如何返回,默认返回nil,但是可以通过元表来设置为调用一个函数,来做自定义的处理,这个函数就是我们说的元方法。
__index 元方法
只是像上面这么说,大家肯定还是不太清楚元表具体是什么,下面通过lua代码来看。
local t = {}
print(t.url) --> nil
-- 通过 getmetatable() 可以取一个表的元表,默认元素为nil
print(getmetatable(t)) --> nil
local base = {url = "daemoncoder.com"}
local mt = {
__index = base
}
-- 通过 setmetatable() 给表设置一个元表
setmetatable(t, mt)
print(t.url) --> daemoncoder.com
上面示例可以看到,表t中原本没有定义url字段,t.url为nil,但是上面例子中给t设置了元表mt,元表中有__index字段的话,t中取不到某个字段时,就会从元表__index字段对应的表(示例中的base变量)中取,因此例子中设置元表后t.url就不为nil了。当然如果base表中依旧没有url字段,会自动继续通过base的元表取。
仔细思考一下会发现,这个和我们平时写代码里的继承关系有点像,我们的子类中如果没有某些东西,会自动从其父类里取,没错,你已经发现了Lua世界里继承的秘密,实在Lua世界里没有像其他语言里对象的定义,所以更别提类的继承关系了,通常Lua里都是用表来模拟对象,用元表来模拟实现继承。
上面的元表定义中,元表中的__index字段的值是一个表,我们还可以改成一个函数,当取不表中的某个字段时,会调用元表中__index对应的函数,看下面示例:
local t = {}
print(t.url) --> nil
local base = {url = "daemoncoder.com"}
local metafunc = function (table, key)
-- 这里的 table 变量就是外层 t 变量传入进来的,key 是当前正在取的字段
if base[key] then
return base[key]
else
print("Warning: " .. key .. " not exist!")
return nil
end
end
local mt = {
__index = metafunc
}
-- 通过 setmetatable() 给表设置一个元表
setmetatable(t, mt)
print(t.url) --> daemoncoder.com
print(t.name) --> 这里t.name返回nil,还会额外输出一行:Warning: name not exist!
这里的__index字段的值是一个函数,就是我们说的__index元方法。
其他常用的元方法
__newindex元方法
和__index元方法类似,__newindex元方法会在给一个表设置一个新增字段时调用,如果元表__newindex对应的值是一个表,则新设置的值会保存到元表中,如果__newindex的值是一个函数,则调用此函数,当然在函数内也可以通过rawset()函数给原有的表设置值。
local t = {}
local mt = {}
-- __newindex 是一个表,新增的字段会在mt上
setmetatable(t, { __newindex = mt })
t.key1 = "value1"
print(t.key1, mt.key1) --> nil value1
-- __newindex 是一个函数,新增字段时会调用此函数
setmetatable(t, {
__newindex = function(mytable, key, value)
print("Adding new item. key: " .. key .. ", value: " .. value)
-- 这里的rawset 等价于mytable[key] = value,不涉及任何元方法
rawset(mytable, key, value)
end
})
t.key2 = 1 --> Adding new item. key: key2, value: 1
print(t.key2, mt.key2) --> 1, nil
__tostring 元方法
当表格改成字段串时__tostring元方法被调用。
local table_string = function(table)
local str = ""
for k, v in pairs(table) do
str = str .. v .. ","
end
return str
end
local t = setmetatable({ 10, 20, 30 }, {
__tostring = table_string
})
print(t) --> 10,20,30,
__call 元方法
当一个表被当作一个函数调用时,__call元方法就会被调用。
local t = setmetatable({10}, {
__call = function(mytable, param)
local sum = 0
for i = 1, #mytable do
sum = sum + mytable[i]
end
for i = 1, #param do
sum = sum + param[i]
end
return sum
end
})
local param = {10,20,30}
print(t(param)) --> 70
__add 元方法
当用+操作两个表时,会调用表的__add元方法。
local table1 = setmetatable({ 1, 2, 3 }, {
__add = function(table1, table2)
for i = 1, #table2 do
table.insert(table1, table_maxn(table1)+1, table2[i])
end
return table1
end,
__tostring = table_string
})
local table2 = {4,5,6}
local t = table1 + table2
print(t) --> 1,2,3,4,5,6,
和__add元方法类似的,还有__sub(减)、__mul(乘)、__div(除)、__eq(等于)、__lt(小于)、__le(小于等于)等。
相关推荐
- 精品博文嵌入式6410中蓝牙的使用
-
BluetoothUSB适配器拥有一个BluetoothCSR芯片组,并使用USB传输器来传输HCI数据分组。因此,LinuxUSB层、BlueZUSB传输器驱动程序以及B...
- win10跟这台计算机连接的前一个usb设备工作不正常怎么办?
-
前几天小编闲来无事就跑到网站底下查看粉丝朋友给小编我留言询问的问题,还真的就给小编看到一个问题,那就是win10跟这台计算机连接的一个usb设备运行不正常怎么办,其实这个问题的解决方法时十分简单的,接...
- 制作成本上千元的键盘,厉害在哪?
-
这是稚晖君亲自写的开源资料!下方超长超详细教程预警!!全文导航:项目简介、项目原理说明、硬件说明、软件说明项目简介瀚文智能键盘是一把我为自己设计的——多功能、模块化机械键盘。键盘使用模块化设计。左侧的...
- E-Marker芯片,USB数据线的“性能中枢”?
-
根据线缆行业的研究数据,在2019年搭载Type-C接口的设备出货量已达到20亿台,其中80%的笔记本电脑和台式电脑采用Type-C接口,50%的智能手机和平板电脑也使用Type-C接口。我们都知道,...
- ZQWL-USBCANFD二次开发通讯协议V1.04
-
修订历史:1.功能介绍1.1型号说明本文档适用以下型号: ZQWL-CAN(FD)系列产品,USB通讯采用CDC类实现,可以在PC机上虚拟出一个串口,串口参数N,8,1格式,波特率可以根据需要设置(...
- win10系统无法识别usb设备怎么办(win10不能识别usb)
-
从驱动入手,那么win10系统无法识别usb设备怎么办呢?今天就为大家分享win10系统无法识别usb设备的解决方法。1、右键选择设备管理器,如图: 2、点击更新驱动程序,如图: 3、选择浏览...
- 微软七月Win8.1可选补丁有内涵,含大量修复
-
IT之家(www.ithome.com):微软七月Win8.1可选补丁有内涵,含大量修复昨日,微软如期为Win7、Win8.1发布7月份安全更新,累计为6枚安全补丁,分别修复总计29枚安全漏洞,其中2...
- 如何从零开始做一个 USB 键盘?(怎么制作usb)
-
分两种情况:1、做一个真正的USB键盘,这种设计基本上不涉及大量的软件编码。2、做一个模拟的USB键盘,实际上可以没有按键功能,这种的需要考虑大量的软件编码,实际上是一个单片机。第一种设计:买现成的U...
- 电脑识别U盘失败?5个实用小技巧,让你轻松搞定USB识别难题
-
电脑识别U盘失败?5个实用小技巧,让你轻松搞定USB识别难题注意:有些方法会清除USB设备里的数据,请谨慎操作,如果不想丢失数据,可以先连接到其他电脑,看能否将数据复制出来,或者用一些数据恢复软件去扫...
- 未知usb设备设备描述符请求失败怎么解决
-
出现未知daousb设备设备描述符请求失du败解决办zhi法如下:1、按下Windows+R打开【运行】;2、在版本运行的权限输入框中输入:services.msc按下回车键打开【服务】;2、在服务...
- 读《飘》47章20(飘每章概括)
-
AndAhwouldn'tleaveMissEllen'sgrandchildrenfornotrashystep-patobringup,never.Here,Ah...
- 英翻中 消失的过去 37(消失的英文怎么说?)
-
翻译(三十七):消失的过去/茱迪o皮考特VanishingActs/JodiPicoult”我能做什么?“直到听到了狄利亚轻柔的声音,我才意识到她已经在厨房里站了好一会儿了。当她说话的时候,...
- RabbitMQ 延迟消息实战(rabbitmq如何保证消息不被重复消费)
-
现实生活中有一些场景需要延迟或在特定时间发送消息,例如智能热水器需要30分钟后打开,未支付的订单或发送短信、电子邮件和推送通知下午2:00开始的促销活动。RabbitMQ本身没有直接支持延迟...
- Java对象拷贝原理剖析及最佳实践(java对象拷贝方法)
-
作者:宁海翔1前言对象拷贝,是我们在开发过程中,绕不开的过程,既存在于Po、Dto、Do、Vo各个表现层数据的转换,也存在于系统交互如序列化、反序列化。Java对象拷贝分为深拷贝和浅拷贝,目前常用的...
- 如何将 Qt 3D 渲染与 Qt Quick 2D 元素结合创建太阳系行星元素?
-
Qt组件推荐:QtitanRibbon:遵循MicrosoftRibbonUIParadigmforQt技术的RibbonUI组件,致力于为Windows、Linux和MacOSX提...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)