当前位置: 首页 > news >正文

3.1 Lua代码中的元表与元方法

什么是元表?

元表 是一个普通的表,可以附加到另一个表上,用来定义该表在某些特定操作下的行为。当 Lua 对表进行某些操作(如相加、索引、调用等)时,如果该表有元表,Lua 就会查看元表中是否有对应的元方法来决定如何执行操作。

可以起到一个类似于c++中运算符重载的作用

tt1={1,2,3,4};
tt2={5,6,7,8,9,10};
meT3={};for index, value in ipairs(tt1) doprint(index,value);
endmeT3.__add=function (t1,t2)local count=0;local res={}if(#t1<#t2)thencount=#t2;elsecount=#t1;endfor i=1,count doif(i<=#t1)and(i<=#t2)thenres[i]=t1[i]+t2[i];elseif i<=#t1 thenres[i]=t1[i];elseif i<=#t2 thenres[i]=t2[i];endendreturn res;
endsetmetatable(tt1,meT3);
setmetatable(tt2,meT3);tt3=tt1+tt2;print("");for index, value in ipairs(tt3) doprint(index,value);
end

运行结果:

1	1
2	2
3	3
4	41	6
2	8
3	10
4	12
5	9
6	10

__index的用法

元表中有键值,table中也有键值,会优先调用table中的键值;table中没有键值的话,会调用元表中的键值


t1={id=123,name="Tom"};
met={__index={age="999"};
};print(t1.age);
t1.age="789";
print(t1.age);setmetatable(t1,met);
print(t1.age);t1.age=nil;
print(t1.age);

运行结果:

nil
789
789
999

元表中的“__index”是一个函数时


t1={id=123,name="Tom"};
met={__index=function (k,v)k[v]="aaa";return "bbb";end
};
print(t1.age);setmetatable(t1,met);
print(t1.age);
print(t1.age);t1.age=nil;
print(t1.age);
print(t1.age);

运行结果:

nil
bbb
aaa
bbb
aaa

__newindex的用法

如果是表,则在表里面设一个没有的key值的时候,会写到__newindex 对应的表中,而不会写到本表中;如果本表中有key值,则会更新本表,不会管元表。如果是function ,则直接调用,且本表,key,value都可以作为参数


t1={id=123,name="Tom"};
t2={};
met={__index={age="hhh";};__newindex=t2;
};setmetatable(t1,met);
print(t1.age);
print("");
t1.age="567";
print(t1.age);
print(t2.age);met.__index=t2;
print(t1.age);
print(t2.age);

运行结果:

hhhhhh
567
567
567

是function的使用方式


t1={id=123,name="Tom"};
t2={};
met={__index={age="hhh";};__newindex=function (t,k,v)rawset(t,k,v);end
};setmetatable(t1,met);
print(t1.age);
print("");
t1.age="567";
print(t1.age);
print(t2.age);met.__index=t2;
print(t1.age);
print(t2.age);

运行结果:

hhh567
nil
567
nil

__index与__newindex对比

基本对比示例

local t = {existing = "已有值"}local mt = {-- __index: 当访问不存在的键时调用__index = function(table, key)print("__index 被调用,键: " .. key)return "默认值 for " .. keyend,-- __newindex: 当设置不存在的键时调用  __newindex = function(table, key, value)print("__newindex 被调用,键: " .. key .. ", 值: " .. value)-- 注意:这里没有实际设置值!end
}setmetatable(t, mt)print("1. 访问已存在的键:")
print(t.existing)  -- 输出: 已有值 (不触发元方法)print("\n2. 访问不存在的键:")
print(t.name)      -- 触发 __index
-- 输出: 
-- __index 被调用,键: name
-- 默认值 for nameprint("\n3. 设置不存在的键:")
t.age = 25         -- 触发 __newindex
-- 输出: __newindex 被调用,键: age, 值: 25print("\n4. 再次访问刚才设置的键:")
print(t.age)       -- 仍然触发 __index! (因为值没有被实际设置)
-- 输出:
-- __index 被调用,键: age  
-- 默认值 for age

__tostring 的用法

__tostring 用函数接管本表的返回值,返回一个string


t1={id=123,name="Tom"};
met={__tostring=function (t)str="";for key, value in pairs(t) dostr=str..key..":\t"..value.."\n";endreturn str;end
};
print(t1);
setmetatable(t1,met);
print(t1);

运行结果:

table: 000000000260b5a0
name:	Tom
id:	123

__call 的用法

类似于默认构造


t1={id=123,name="Tom"};
met={__call=function (t,...)local tt={...}for key, value in pairs(t) doprint(key,value);endfor key, value in pairs(tt) doprint(key,value);endend
};
setmetatable(t1,met);
t1(1,2,3,"io","900");

运行结果:

name	Tom
id	123
1	1
2	2
3	3
4	io
5	900

rawget(t,str) 是获取本表 t 中 str 的值,不是获取元表中的值


t1={id=123,name="Tom"};
met={__index={age="123"};
};print(t1.name);
print(t1.age);
setmetatable(t1,met);
print("");
print(t1.name);
print(t1.age);print("");
print(rawget(t1,"name"));   --获取本表中的值
print(rawget(t1,"age"));

运行结果:

Tom
nilTom
123Tom
nil
http://www.dtcms.com/a/544680.html

相关文章:

  • Rust——多重借用的冲突解决方案:驾驭Rust借用检查器的艺术
  • kaggle比赛与常用的dash board 3lc
  • 适配器模式:让不兼容的接口协同工作
  • Neo4j中导入.owl数据
  • 应急救援 “眼观六路”:SA/NSA 双模覆盖,偏远灾区也能实时传视频
  • 站长工具短链接生成网站中队人物介绍怎么做
  • 【Spring Boot + Spring Security】从入门到源码精通:藏经阁权限设计与过滤器链深度解析
  • 《嵌入式硬件(十七):基于IMX6ULL的温度传感器LM75a操作》
  • 用 Go 手搓一个内网 DNS 服务器:从此告别 IP 地址,用域名畅游家庭网络!
  • Rust async/await 语法糖的展开原理:从表象到本质
  • Rust 零拷贝技术:从所有权到系统调用的性能优化之道
  • 浪潮服务器装linux系统步骤
  • 视频网站服务器带宽需要多少?视频网站服务器配置要求
  • 《嵌入式硬件(十八):基于IMX6ULL的ADC操作》
  • 注册网站发财的富豪北京公司如何做网站
  • 仓颉语言异常捕获机制深度解析
  • 基于SAP.NET Core Web APP(MVC)的医疗记录管理系统完整开发指南
  • 咖啡网站建设设计规划书wordpress修改首页网址导航
  • C#WPF UI路由事件:事件冒泡与隧道机制
  • 神经网络时序预测融合宏观变量的ETF动态止盈系统设计与实现
  • 分布式Session会话实现方案
  • Java创建【线程池】的方法
  • 相机直播,HDMI线怎么选择
  • 做外贸哪些国外网站可以推广上海中学地址
  • HFSS微带线仿真
  • 推荐常州微信网站建设网站友链怎么做
  • 多模态的大模型文本分类模型代码(二)——模型初步运行
  • 强化特权用户监控,守护Active Directory核心安全
  • Kafka Consumer 消费流程详解
  • 安全守护者:防爆外壳在气体传感器领域的关键应用