Lua 元表和元方法
创始人
2024-03-08 04:35:04
0

文章目录

  • 1. 元表(Metatable)
  • 2. 元方法
    • 2.1 __add(对表进行"+"操作时触发)
      • 2.1.1 其它操作符的方法
      • 2.2.2 注意事项
    • 2.2 __tostring (print()时触发)
    • 2.3 __index (访问表中不存在属性时触发)
    • 2.4 __newindex(对table中不存在的字段赋值时调用)

1. 元表(Metatable)

元表是普通的Lua表,定义了原始值在某些特定操作下的行为。
我们称元表中的键为事件,称值为元方法
设置(SetMetatable)/获取(GetMetatable)元表:
SetMetatable 的两种写法:

local mt = {}
setMetatable(t, mt)setMetatable(t, {__add = function() end})
local mt = {}
local t = {}
print(getmetatable(t))          // nil
setmetatable(t, mt)             // 设置表 t 的元表为 mt
print(mt)
print(getmetatable(t))          // 获取元表地址 和上面打印的 mt 地址相同

输出结果:

nil
table: 000001ECD17E3940
table: 000001ECD17E3940

2. 元方法

2.1 __add(对表进行"+"操作时触发)

local mt = {}mt.__add = function(tab1, tab2)local resTab = {}local len = math.max(#tab1, #tab2)if len == 0 then return resTab endfor i = 1, len, 1 doif type(tab1[i]) == "nil" then tab1[i] = 0 endif type(tab2[i]) == "nil" then tab2[i] = 0 endresTab[i] = tab1[i] + tab2[i]endreturn resTab
endlocal tab1 = {1, 2, 3}
local tab2 = {4, 5, 6}setmetatable(tab1, mt)
setmetatable(tab2, mt)local resTab = tab1 + tab2for index, value in ipairs(resTab) doprint(value)
end

输出结果:

5
7
9

2.1.1 其它操作符的方法

元方法对应运算符
__add+
__sub-
__mul*
__div/
__mod%
__concat…(连接符)
__eq==
__lt<
__le<=

2.2.2 注意事项

当涉及二元操作符时:两表元表有以下情况

  • 相同元表:执行元表中的元方法
  • 不同元表:第一个值有元表(操作符前面),就以这个元表为准看是否有元方法,
    如果没有就看第二个元表是否有元方法。
  • 都没有元表:报错
local mt1 = {}
local mt2 = {}mt1.__sub = function(t1,t2)print("mt1->sub")
endmt2.__sub = function(t1,t2)print("mt2->sub")
endlocal t1 = {}
local t2 = {}
local t3 = {}setmetatable(t1,mt1)    -- 设置mt1为t1(普通表)的元表
setmetatable(t2,mt2)    -- 设置mt2为t2(普遍表)的元表local res1 = t1 - t2    -- 计算过程中调用元表的mt1.__sub元方法 mt1->sublocal res2 = t2 - t1    -- 计算过程中调用元表的mt2.__sub元方法 mt2->sublocal res3 = t3 - t1    -- 由于t3没有元表 __sub元方法,所以调用t1的元表中的元方法 mt1->sub

2.2 __tostring (print()时触发)

local mt = {}mt.__tostring = function(tab)local str = ""for index, value in pairs(tab) dostr = str .. index .. "--" .. value .. "\n"endreturn str
endlocal tab = {1, 2, 3}setmetatable(tab, mt)print(tab)

输出结果:

1--1
2--2
3--3

2.3 __index (访问表中不存在属性时触发)

1. __index 是一个表

local mt = {}
mt.__index = {sex = "boy"}local tab = {name = "ming", age = 18}print(tab.name, tab.age)    -- ming 18
print(tab.sex)          -- nilsetmetatable(tab, mt)print(tab.sex)          -- boy
print(tab.enjoy)        -- nil

2. __index 是一个函数

local mt = {}
mt.__index = function(table,key)print(table) -- 打印t表print(key) -- 打印name
endlocal t = {}
setmetatable(t,mt)print(t.name) -- t表不可以找到,调用元表的 __index 元方法

输出结果:

table: 0000026EFEE9F4C0
name
nil

2.4 __newindex(对table中不存在的字段赋值时调用)

1. 普通表修改键值
存在则修改,不存在就会增加

local t = {name = "Y"}
t.name = "YY" -- 修改
t.age = 23	  -- 添加for key , value in pairs(t) do --无序遍历字典类型表print(key .. " : " .. value)
end

输出结果:

age : 23
name : YY

2.__newindex是一个函数
调用_newindex函数,但是不会给元表赋值

local mt = {}mt.__newindex = function(table, key, value)print(table)print("key:" .. key)print("value:" .. value)endlocal t = {}
setmetatable(t,mt)print(t.name) -- nil
t.name = "YY" 
print(t.name) -- 赋值后 先调用__newindex函数然后打印 nil

输出结果:

nil
table: 0000012C2529F5F0
key:name
value:YY
nil

3.__newindex是一个表
如果普通表没有该变量,那么到元表查找,并在元表新增或修改变量值

local k = {name = "ming"}
local mt ={}
mt.__newindex = klocal t = {}
setmetatable(t,mt)
print(t.name) -- nil  查询
print(k.name) -- Y    查询t.name = "YY" -- 到对应的k表 修改
print(k.name) -- YY   查询  
print(t.name) -- nil  查询

输出结果:

nil
ming
YY
nil

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...