Lua—元表(Metatable)

原表解析

在 Lua table 中我们可以访问对应的 key 来得到 value 值,但是却无法对两个 table 进行操作(比如相加)。
因此 Lua 提供了元表(Metatable),允许我们改变 table 的行为,每个行为关联了对应的元方法。

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

原表的定义

lua 复制代码
mytable={}      --普通表
mymetatable={}  --元表
setmetatable(mytable,mymetatable) --将mymetatable设置为mytable的原表

--可简写如下:
mytable=setmetatable({},{})

getmetatable(mytable) --会返回mytable的元表

原表的应用

1. 变量赋值

解析如下:

lua 复制代码
mymetatable={}
mytable=setmetatable({k1="v1"},{__newindex=mymetatable})

mytable.newkey="v2"
print(mytable.newkey,mymetatable.newkey)
--输出:nil   v2  :普通表中不含"newkey",会调用元方法

mytable.k1="newV"
print(mytable.k1,mymetatable.k1)
--输出:newV   nil :普通表中含有K1,会进行赋值,不再调用元方法

2.元方法调用函数

lua 复制代码
mytable=setmetatable({k1="v1"},{
    __newindex=function(mytable,k,v)--重写元方法
      rawset(mytable,k,"\""..v.."\"")--rawset绕过原表机制,直接向原表中插入新键值对
      end
    })
  mytable.k1="new v1";
  mytable.k2=3;--由于初始表中不k2,则会向元表中查询元方法
  print(mytable.k1,mytable.k2);
  
  --输出:v1   "3"

3.合并元表

lua 复制代码
function table_max(t)--获取原表最大键
  --用"#"或者table.getn时,若键不连续,只会获取第一段的最大值
  maxk=0;
  for k,v in pairs(t) do
    if type(k)=="number" and k>maxk then
      maxk=k
    end
  end
  return maxk
end

--实现两表合并
mytable=setmetatable({1,2,3},{__add=function(mytable,newtable)
      local mytable_maxk=table_max(mytable)
      for i=1,table_max(newtable) --遍历newtable
        table.insert(mytable,mytable_maxk+i,newtable[i])
        --将newtable中的数据插入到mytable中
      end
      return mytable
    end
  })

newtable={4,5,6}
mytable=mytable+newtable

for k,v in pairs(mytable) do
  print(k.."--"..v)
end
元方法 运算操作
__add "+"
__sub "-"
__mul "*"
__div "/"
__mod "%"
__unm "-"
__concat "..."
__eq "=="
__it "<"
__le "<="

注:"__"两个下划线,__sub对应二元减(两个参数);__unm对应一元减(只有一个参数)。

相关推荐
devilnumber3 小时前
Java 递归算法 详解 + 核心要点 + 实战运用 + 避坑指南
java·开发语言·算法
asdfg12589635 小时前
JavaBean是什么?怎么理解?有什么用途?
java·开发语言
dsyyyyy11015 小时前
JavaScript变量
开发语言·javascript·ecmascript
z落落6 小时前
C#WinForm 窗体切换与窗体传值(登录跳转案例)+WinForm 窗体传值(从上往下传、从下往上传)
开发语言·windows·c#
allway26 小时前
How to Echo Multiline to a File in Bash [3 Methods]
开发语言·chrome·bash
weixin_462446236 小时前
手把手教你用 Bash 脚本自动更新 /etc/hosts —— 自动绑定网卡 IP 与节点名
开发语言·tcp/ip·bash
一个梦醒了6 小时前
安装git bash选项推荐
开发语言·git·bash
ct9787 小时前
React 状态管理方案深度对比
开发语言·前端·react
数量技术宅7 小时前
2026量化前沿:从Reddit热帖到Python实战,如何用赫斯特指数(Hurst)狙击虚假突破?
开发语言·python
华如锦7 小时前
面了很多 Java转AI Agent方向,一些面试题总结
java·开发语言·人工智能·python·ai