Lua 元表和元方法
一、元表
元表可以修改一个值在面对一个未知操作时的行为,Lua 中使用 table 作为元表的承载。
元表只能给出预先定义的操作集合的行为,比类会更加受限制,不支持继承。
Lua 每一个值都可以有元表 :
- 表和用户数据类型都具有各自独立的元表;
- 其他类型的值则共享对应类型所属的同一个元表;
二、元表的设置
1、类型的原始元表
Lua 中,元表的设置只能针对 table ,其他类型都不能设置。
table 的初始化元表为 nil ,即没有设置元表,只能通过 setmetatable
进行设置,多个 table 可以共享一个 table 作为元表(当然也可以使用他自己作为自己的元表,因为他自身也是一个 table)
Lua 只有 string 初始化了元表,而且是针对了所有的字符串,即 string 都是同一个元表。其他的类型为 nil 。
print("表的初始值", getmetatable({})) --> 表的初始值 nilprint("整型的初始值", getmetatable(10)) --> 整型的初始值 nil
print("浮点型的初始值", getmetatable(10.0)) --> 浮点型的初始值 nil--- 通过打印可以看到两个字符串的元表是同一个
print("字符串的初始值", getmetatable("江澎涌")) --> 字符串的初始值 table: 0x600000b14640
print("字符串的初始值", getmetatable("jiangpengyong")) --> 字符串的初始值 table: 0x600000b14640print("布尔型的初始值", getmetatable(true)) --> 布尔型的初始值 nilprint("nil的初始值", getmetatable(nil)) --> nil的初始值 nilfunction sayHello() end
print("函数的初始值", getmetatable(sayHello)) --> 函数的初始值 nil
2、设置元表和获取元表
2-1、setmetatable(table, metatable)
给表 table 设置元表 metatable
参数
- table:要被设置元表的表
- metabale:元表,如果值为 nil ,则表明要删除 table 的原有元表。如果原来的元表有
__metatable
字段,则不能再设置元表,否则会抛出异常cannot change a protected metatable
__metatable
会在下面的 “表相关方法” 小节分享
返回值:
返回被设置元表的表,就是参数 table
2-2、getmetatable(object)
如果 object
没有元表,则返回 nil
如果对象 Object 有元表,且该元表有一个 "__metatable"
字段,则返回关联的值。否则,返回给定对象 Object 的元表
2-3、举个例子
local oriTable = {}
local metaTable = {}
print(setmetatable(oriTable, metaTable), oriTable, metaTable) --> table: 0x600001ac0840 table: 0x600001ac0840
print(getmetatable(oriTable), metaTable) --> table: 0x600001ac0900 table: 0x600001ac0900
给元表带有 __metatable
字段的表,设置新的元表,则会抛出异常(见下图)
t2 = { c = 1 }
t2.__metatable = { a = 1 }
s1 = {}
setmetatable(s1, t2)
print('getmetatable(s1)["a"]', getmetatable(s1)["a"]) --> getmetatable(s1)["a"] 1-- 此处会抛出异常:cannot change a protected metatable
print(setmetatable(s1, {}))
三、元表方法
1、具有的元方法
元表方法方法很像 kotlin 中的操作符方法
1-1、算术运算符
元表方法 | 含义 |
---|---|
__add | 加法 |
__mul | 乘法 |
__sub | 减法 |
__div | 除法 |
__floor | floor除法 |
__unm | 负数 |
__mod | 取模 |
__pow | 幂运算 |
__band | 按位与 |
__bor | 按位或 |
__bxor | 按位异或 |
__bnot | 按位取反 |
__shl | 向左移 |
__shr | 向右移 |
__concat | 定义连接运算符 |
1-2、关系运算符
元表方法 | 含义 |
---|---|
__eq | 等于 |
__lt | 小于 |
__le | 小于等于 |
值得注意: ~=
、a > b
、a >= b
没有对应的元方法,会被转为如下
a ~= b
会被转为not( a == b)
a > b
会被转为b < a
a >= b
会被转为b <= a
关系运算符遇到两个不同类型的对象,则会直接返回 false ,不会进行搜寻任何的元方法
1-3、库相关方法
元表方法 | 含义 |
---|---|
__tostring | 当调用 tostring 时,会先检查值是否有一个元方法 __tostring ,有则会先使用。 |
__metatable | 使用该元方法可以保护元表,用户无法获取也无法修改该元表。当元表设置了 __metatable 的字段,则 getmetatable 会返回这个字段的值,而 setmetatable 则会引发错误 |
__pairs | 从 Lua 5.2 开始,当元表拥有一个 __pairs 的元方法时,pairs 会调用这个元方法来完成遍历 |
1-4、表相关方法
元表方法 | 含义 |
---|---|
__index | 一旦访问 table 中不存在的字段,正常情况下会返回 nil 。如果设置了这个元表方法,则会调用自身元表对应的该 __index 元方法,并以被调用的表(即此处的 table ,不是元表)和键作为参,进行调用。也可以给 __index 设置一个 table,这样就会直接在这table 中查询,速度比方法稍快。可以通过 rawget 获取原始数据,不考虑元表。 |
__newindex | 当调用 table 进行索引赋值时,如果设置了该元表方法,则会使用被调用的表(即此处的 table ,不是元表),键和值作为参,调用该方法。同样也可以给 __newindex 设置一个表,则会将值直接存至该表。可以通过 rawset(talbe, key, value) 相当于 table[key] = value 进行直接对 table 的赋值,不考虑元表。 |
__len | 获取 table 的长度时,会调用该方法,获取长度 |
__index
和 __newindex
的异同
- 相同点:两个函数都是发生在 table 中没有对应的 key 时触发
- 不同点:当前需要的索引没有对应的值时则调用
__index
,如果 table 设置值时,则调用__newindex
2、元方法的搜索
如果两个变量相加,搜索规则如下:
- 先查看第一个值是否有元表,并且是否存在所需元方法,如果存在则使用该元方法,此时第二个值的元方法被忽略。否则进入下一条
- 查看第二个值是否有元表,并且是否存在所需的元方法,如果有则进行使用。否则进入第三条
- 抛出异常
3、举个例子
这里元方法比较多,就不一一粘贴代码了,不然会让文章非常冗长。建议各位童鞋们移步 github clone 下代码自行运行一下会更加深刻理解。
“算术运算符” 、 “关系运算符”、“库相关方法” 相关的代码 可以查看以下的代码:
集合.lua:https://github.com/zincPower/lua_study_2022/blob/master/13%20%E5%85%83%E8%A1%A8%E3%80%81%E5%85%83%E6%96%B9%E6%B3%95/%E9%9B%86%E5%90%88.lua
集合调用.lua:https://github.com/zincPower/lua_study_2022/blob/master/13%20%E5%85%83%E8%A1%A8%E3%80%81%E5%85%83%E6%96%B9%E6%B3%95/%E9%9B%86%E5%90%88%E8%B0%83%E7%94%A8.lua
“表相关方法” 相关的代码
表相关元方法.lua:https://github.com/zincPower/lua_study_2022/blob/master/13%20%E5%85%83%E8%A1%A8%E3%80%81%E5%85%83%E6%96%B9%E6%B3%95/%E8%A1%A8%E7%9B%B8%E5%85%B3%E5%85%83%E6%96%B9%E6%B3%95.lua
四、写在最后
Lua 项目地址:Github传送门 (如果对你有所帮助或喜欢的话,赏个star吧,码字不易,请多多支持)
如果觉得本篇博文对你有所启发或是解决了困惑,点个赞或关注我呀。
公众号搜索 “江澎涌”,更多优质文章会第一时间分享与你。
相关文章:
Lua 元表和元方法
一、元表 元表可以修改一个值在面对一个未知操作时的行为,Lua 中使用 table 作为元表的承载。 元表只能给出预先定义的操作集合的行为,比类会更加受限制,不支持继承。 Lua 每一个值都可以有元表 : 表和用户数据类型都具有各自…...
【Git】01-Git基础
文章目录 Git基础1. 简述1.1 版本管理演变1.2 Git的特点 2. Git安装2.1 安装文档2.1 配置user信息 3. 创建仓库3.1 场景3.2 暂存区和工作区 4. 重命名5. 常用git log版本历史5.1 查看当前分支日志5.2 简洁查看日志5.3 查看最近指定条数的日志 6. 通过图形界面工具查看版本7. 探…...
【Vue2.0源码学习】生命周期篇-初始化阶段(initState)
文章目录 1. 前言2. initState函数分析3. 初始化props3.1 规范化数据3.2 initProps函数分析3.3 validateProp函数分析3.4 getPropDefaultValue函数分析3.5 assertProp函数分析 4. 初始化methods5. 初始化data6. 初始化computed6.1 回顾用法6.2 initComputed函数分析6.3 defineC…...
专升本英语零基础学习
1. 词法 1.1 名词 名词(n.),是词类的一种,属于实词。他表示人,物,事,地点或抽象概念的统一名称。 1.1 名词的含义 名词(n.),是词类的一种,属于实词。他表示人&#x…...
QUIC协议连接详解(二)
目录 一:RTT解释 二:QUIC 1-RTT连接 三:QUIC 0-RTT连接 一:RTT解释 在介绍QUIC协议的连接之前先科普一下什么是RTT。RTT是Round-Trip Time的英文缩写,翻译过来就是一趟来回的时间即往返时延。时间计算即从发送方发送…...
JAVA 经常遇到一些问题【第二部分36~51】
重拾者: 每日记录至目前(记录51种不同场景的问题可参考解决方案) 异常就两部分: 1、excepiton信息: 报错产生的原因 2、at开头表示: 异常产生的代码位置。 欢迎关注本人微信公众号:AIM…...
蓝桥杯打卡Day6
文章目录 N的阶乘基本算术整数查询 一、N的阶乘OI链接 本题思路:本题是关于高精度的模板题。 #pragma GCC optimize(3) #include <bits/stdc.h>constexpr int N1010;std::vector<int> a; std::vector<int> f[N];std::vector<int> mul(in…...
spark集群问题汇总
一、 磁盘问题 问题描述可能原因解决措施core节点磁盘不足, 并且持续增加未开启spark-history的日志清理打开日志清理: spark.history.fs.cleaner.enabled task节点磁盘不足 APP应用使用磁盘过大: 1. 严重的数据倾斜 2. 应用本身数据量大 1. 解决数据倾斜 2. 加大资源, 增加e…...
WebServer 解析HTTP 请求报文
一、TCP 状态转换 浏览器访问网址,TCP传输全过程 二、TCP协议的通信过程 三、TCP 通信流程 // TCP 通信的流程 // 服务器端 (被动接受连接的角色) 1. 创建一个用于监听的套接字- 监听:监听有客户端的连接- 套接字:这…...
Golang开发--interface的使用
在Go语言中,接口(interface)是一种特殊的类型,它定义了一组方法的集合。接口为实现多态性提供了一种机制,允许不同的数据类型实现相同的方法,从而可以以统一的方式处理这些不同类型的对象。接口在Go中广泛用…...
2023 年高教社杯全国大学生数学建模竞赛题目 B 题 多波束测线问题
B 题 多波束测线问题 单波束测深是利用声波在水中的传播特性来测量水体深度的技术。声波在均匀介质中作匀速直线传播,在不同界面上产生反射,利用这一原理,从测量船换能器垂直向海底发射声波信号,并记录从声波发射到信号接收的传播…...
leetcode算法题--生成特殊数字的最少操作
原题链接:https://leetcode.cn/problems/minimum-operations-to-make-a-special-number/description/ 感觉还是比较难想到的。。 func minimumOperations(num string) int {res : len(num)if strings.Contains(num, "0") {res-- }f : func(tail string)…...
数学建模--决策树的预测模型的Python实现
目录 1.算法流程简介 2.算法核心代码 3.算法效果展示 1.算法流程简介 """ 决策树的应用:对泰坦尼克号数据集成员进行预测生死 算法流程还是比较简单的,简单学习一下决策树跟着注释写即可 文章参考:https://zhuanlan.zhihu.com/p/133838427 算法种遇上sklear…...
Linkstech多核并行仿真丨光伏发电系统模型及IEEE 39 bus模型多核并行实测
新能源场站和区域电网作为复杂且具有动态特性的大规模电力系统,需要实时仿真测试来验证其性能、稳定性和响应能力。在这种背景下,多核并行仿真运算显得尤为重要。多核并行仿真能够同时处理电力系统的复杂模型,加速仿真过程,实现接…...
在STS里使用Gradle编译Apache POI5.0.0
1、到官方下面地址下载Gradle最新的版本 Gradle Distributions 2、解压后拷贝到D盘下D:\gradle-8.3-rc-4里 3、配置环境变量 新建系统变量 GRADLE_HOME ,值为 路径 4、在 Path 中添加上面目录的 bin 文件路径 (可以用 %GRADLE_HOME%\bin,…...
golang - 使用有缓冲通道控制并发数
在 Go 语言中,使用带缓冲的通道(buffered channels)可以有效地控制并发数。带缓冲的通道可以让你限制同时运行的 goroutine 数量,从而避免过度并发导致的资源耗尽问题。以下是一个使用带缓冲通道控制并发数的示例: pa…...
AUTOSAR测试指标
测试方法 1、测试相关时间2、检查各个状态下ECU的情况3、程序编写 1、测试相关时间 序号时间参数描述测试方法时间1T_Wakeup从睡眠模式到网络模式,(上位机)发送NM报文的时间唤醒源的时间100ms2T_START_NM从睡眠模式到网络模式,DUT发送的第一帧NM报文捕获…...
Vue 前端项目使用alibaba矢量库svg图标
Vue 前端项目使用alibaba矢量库svg图标 这里主要是记录 vue项目中使用阿里矢量库图标的操作流程,方便以后查阅!!! 一、简介 iconfont 是由阿里巴巴体验团队打造的,一款设计和前端开发的便捷工具.拥有着很强大且图标内…...
蓝桥杯官网填空题(距离和)
题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 两个字母之间的距离定义为它们在字母表中位置的距离。例如 A 和 C 的距离为 2,L 和 Q 的距离为 5。 对于一个字符串,我们称字符串中两两字符…...
【座位调整】Python 实现-附ChatGPT解析
疫情期间课堂的座位进行了特殊的调整,不能出现两个同学紧挨着,必须隔至少一个空位,给你一个整数数组desk,表示当前座位的占座情况,由若于0和1组成,其中 0 表示没有占位,1表示占位。在不改变原有座位秩序情况下,还能安排坐几个人? 输入描述: 第一行是一个数组,表示作为…...
前端面试基础面试题——5
1.react 和 vue 的区别是什么? 2.虚拟DOM的原理?优点与缺点? 3.类组件和函数组件之间的区别是? 4.state 和 props 区别是什么? 5.React 中 refs 是做什么的? 6.什么是高阶组件? 7.讲讲什么…...
Java高并发系列: 使用wait - notify实现高效异步方法
1. 背景 在项目开发中, 通常会有异步执行操作, 例如: 提交一个异步清空一系列数据库中ID ${_id} 的记录, 这个时候通常的做法是主线程将任务添加到一个异步队列中, 后台维护一个线程不断地循环扫描这个队列, 如果有需要执行的任务, 则执行相应的逻辑. 如下图所示: 2. 一个简…...
业务安全详解
文章目录 一、 业务安全概述1.1 业务安全现状1.1.1 业务逻辑漏洞1.1.2 黑客攻击的目标 二、 业务安全测试2.1 业务安全测试流程2.1.1 测试准备2.1.2 业务调研2.1.3 业务建模2.1.4 业务流程梳理2.1.5 业务风险点识别2.1.6 开展测试2.1.7 撰写报告 三、 业务安全经典场景3.1 业务…...
算法笔记--最大连续1的个数Ⅲ
leetcode题目链接:1004. 最大连续1的个数 III 题目描述 给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。 思路 这里可以转换思路,让题意更加明确:即,求一个最大连续区间…...
Linux CentOS7 添加中文输入法
在安装CentOS7时,现在默认安装了桌面中文系统。可以切换为英文,中英文可以按要求随时更换。而在CentOS7桌面环境下,显示中文非常方便、正确,但不能录入中文。 在远程登录系统的情况下,不论是系统语言(LANG…...
Python接口自动化封装导出excel方法和读写excel数据
一、首先需要思考,我们在页面导出excel,用python导出如何写入文件的 封装前需要确认python导出excel接口返回的是一个什么样的数据类型 如下:我们先看下不对返回结果做处理,直接接收数据类型是一个对象,无法获取返回值…...
React三属性之:refs
作用 refs是为了获取节点,使用场景主要在需要操作dom的时候,比如echarts,就需要真实的dom节点 使用 import React from "react"; class RefsTest extends React.Component{state {value:输入框的值}refPlan React.createRef()logRef ()>{console.log(this.r…...
将Vue项目迁移到微信小程序中
文章目录 一、创建一个Vue.js的应用程序二、构建微信小程序1. 安装微信小程序构建工具2. 在vuejs项目的根目录中创建一个wepy.confgjs文件3. 在vuejs项目的根目录中运行构建 三、错误记录1. 找不到编译器:wepy-compiler-sass 一、创建一个Vue.js的应用程序 使用 Vu…...
php权限调整强制用户退出的解决方案
要强制用户重新登录,你可以采取以下步骤: 当用户登录时,将用户的登录状态和其他相关信息存储在服务器端。例如,你可以将用户ID、用户名或其他标识符存储在服务器的会话(session)中。当管理员修改用户的某些…...
[uniapp]踩坑日记 unexpected character > 1或‘=’>1 报错
在红色报错文档里下滑,找到Show more 根据提示看是缺少标签,如果不是缺少标签,看看view标签内容是否含有<、>、>、<号,把以上符合都进行以<号为例做{{“<”}}处理...
做赌博网站赚/去了外包简历就毁了吗
var foo{rzx:1} var bar foo; foo.xfoo{rzx:100} console.log(foo.x) console.log(bar.x) 有这样一个热门问题: var a {n: 1}; var b a; a.x a {n: 2}; alert(a.x); // --> undefined alert(b.x); // --> {n: 2} 其实这个问题很好理解,关键要弄…...
linux把wordpress/免费网站自助建站系统
当系统卡顿、出现 Bug、电脑崩坏的时候,应该重启,重装,还是重买呢?相信大多数网友对重装并不陌生了,PE 系统、系统重置、在线重装降低了重装系统的门槛,「重装大法」虽然可以解决 90% 的问题,简…...
越秀网站建设推广/近期热点新闻
记者今天从上海律师协会了解到,截至2019年底,上海共有1660家律所、26520名律师。 数据还进一步显示了2019年上海律师行业的情况——哪个区的律师最多?律师男女比例如何?律师业务承办量增长了多少……浦东律师数量最多,…...
h5网站设计/做网站推广的公司
四、学习逆变(DC-AC)电路和LLC的基本工作原理。 全桥逆变电路包括单相全桥逆变电路和三相全桥逆变电路,逆变的主要功能是把直流电逆变成某一频率或可变频率的交流电供给负载。 单相半桥逆变电路基本工作原理 第一阶段,VT1基极脉…...
h5网站开发软件下载/站长之家官网登录入口
问题 Push failed: fatal: Authentication failed for httpspycharm invalid authentication data couldn’t kickstart handshaking 解决...
银川做网站哪家好/江苏建站
给大家推荐一个实用面试题库 1、前端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 前端面试基础知识题 1. js中如何判断一个值是否是数组类型? instanceof const arr []; arr instanceof…...