Lua 只读表

Lua 的 table 建立只读机制,保护 table 不能被随意修改。

建立只读机制

Lua 的 table 通常情况下是可以随意修改字段的值,或者新增字段。

如果想要建立只读机制,保护表只能读取,而不能被随意修改,可以利用元表。

禁止新增字段

首先,利用 __newindex,可以禁止新增字段。

例如,现在有一个 student 表,包含 name 和 age。

定义一个 mt 表,__newindex 打印只读提示。

给 student 表设置元表 mt。

local student = {name = "Alice",age = 18
}local mt = {__newindex = function ()print("Can not modify a readonly table")end
}setmetatable(student, mt)

现在可以读取字段,但是不能新增字段了。

例如给 student 增加一个 score 字段,但是会打印只读提示,没有赋值,尝试打印 score 字段会输出 nil。

local name = student.name
print(name)  -- Alicestudent.score = 0     -- Can not modify a readonly table
print(student.score)  -- nil

禁止修改字段

经过上述步骤后,虽然不能新增字段,但还是可以对已有的字段进行修改。

student.age = 20
print(student.age)  -- 20

Lua 没有提供修改字段的元方法,不过我们可以利用空表,把修改字段的行为,转化成新增字段的行为。

因为对于空表来说,访问任何字段都是不存在的,都会是新增字段的行为。

修改一下之前的代码,定义一个 empty 表,给 empty 设置元表 mt,元表里定义 __index,赋值为 student。

local student = {name = "Alice",age = 18
}local empty = {}
local mt = {__index = student,__newindex = function ()print("Can not modify a readonly table")end
}
setmetatable(empty, mt)

此时,访问 empty 表,是不能修改字段值的。

empty.age = 20    -- Can not modify a readonly table
print(empty.age)  -- 18

不过,此处仍然可以直接去修改 student 表,所以需要对这套方法做一个封装。

封装只读函数

定义一个全局函数 Readonly,把上述的步骤放到函数中,接收一个 table,返回经过处理的空表。

Readonly = function (table)local empty = {}local mt = {__index = table,__newindex = function ()print("Can not modify a readonly table")end}setmetatable(empty, mt)return empty
endlocal student = {name = "Alice",age = 18
}
student = Readonly(student)

再尝试一下修改 student,已经不能修改字段的值了。

student.age = 20    -- Can not modify a readonly table
print(student.age)  -- 18

嵌套表

上面的只读函数只能处理一层表,如果表里面还嵌套了表,那么嵌套的表还是非只读的。

此时可以递归检查表里是否有嵌套表。

Readonly = function (table)-- 遍历每个字段for key, value in pairs(table) do-- 有嵌套表if type(value) == "table" then-- 递归设置只读table[key] = Readonly(value)endend-- 设置只读的步骤local empty = {}local mt = {__index = table,__newindex = function ()print("Can not modify a readonly table")end}setmetatable(empty, mt)return empty
end

在 student 表里新增一个 score 表,包含 math 和 english 字段。

经过只读函数递归处理之后,score 表也是只读的。

local student = {name = "Alice",age = 18,score = {math = 100,english = 100}
}
student = Readonly(student)student.score.math = 20    -- Can not modify a readonly table
print(student.score.math)  -- 100

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/28236.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python编程环境搭建

简介: Python环境安装比较简单,无需安装其它依赖环境,主要步骤为: 1. 下载并安装Python对应版本解释器 2. 下载并安装一个ide编码工具 一、下载并安装Python解释器 1.1 下载 官网地址:Welcome to Python.org 选择…

一次数据库连接泄漏导致的响应迟缓

数据库连接池泄漏其实非常普遍,本文简单记一次数据库连接池泄漏问题,排查和思考。 问题与分析 问题:服务器上的负载激增, Postgres 查询的时间和CPU消耗都异常飙升。 分析:经过调试,得出以下分析&#x…

Java云HIS医院管理系统源码 B/S架构 一体化电子病历系统源码 基于云端SaaS平台源码,采用B/S(Browser/Server)架构

“云”指系统采用云计算的技术和建设模式,具有可扩展、易共享、区域化、易协同、低成本、易维护、体验好的优势。“H”是医疗卫生,由原来医院 (Hospital)到现在的医疗卫生 (Healthcare),拓展了 H的内涵与外延。云 HIS 重新定义了医院信息系统…

[Python学习篇] Python条件语句

if 语法: if 条件: 条件成立执行的代码1 条件成立执行的代码2 ...... 示例: if False:print("条件成立我执…

【笔记】为什么不同硬件的1T实际硬盘容量硬盘是954GB或者931GB?

问题描述 不管是电脑还是移动硬盘,厂家描述的1T硬盘容量都不是计算机知识领域内真正的1T大小,硬盘容量实际是小于1TB的。 另外还发现对于1TB的不同厂家设备有着实际不同的磁盘容量,比如为什么有的1T电脑硬盘是954GB,而移动硬盘是…

9、Spring之Bean生命周期~依赖注入(总)

9、Spring之Bean生命周期~依赖注入(总) 依赖注入spring有几种依赖注入方式源码解析 依赖注入 spring有几种依赖注入方式 从类型角度区分,分两种:手动和自动 手动注入:通过XML中定义Bean时,可手动注入 &l…

用Python分析《三国演义》中的人物关系网

用Python分析《三国演义》中的人物关系网 三国演义获取文本文本预处理分词与词频统计引入停用词后进行词频统计构建人物关系网完整代码 三国演义 《三国演义》是中国古代四大名著之一,它以东汉末年到晋朝统一之间的历史为背景,讲述了魏、蜀、吴三国之间…

git 删除已经不存在于远程仓库中的本地分支

git 删除远程仓库中已经不存在的本地远程分支跟踪副本 git fetch --prune 是一个Git命令,它用于从远程仓库获取并更新所有分支的引用,同时删除那些已经不存在于远程仓库中的本地分支。请注意,这个命令不会直接删除你正在工作的本地分支&…

流行跨链桥总结

本贴主要总结出现的新跨链桥,简介,及其项目主页,持续更新 1.Cbridge cBridge引入了一流的跨链Token桥接体验,为用户提供了深度流动性,为不想运营cBridge节点的cBridge节点运营商和流动性提供商提供了高效且易于使用的…

zabbix自定义监控mysql状态和延迟

zabbix自定义监控mysql状态和延迟 文章目录 zabbix自定义监控mysql状态和延迟zabbix自定义监控mysql状态配置主从配置自定义监控添加监控项添加触发器模拟测试异常 zabbix自定义监控mysql延迟配置自定义监控添加监控项添加触发器测试 zabbix自定义监控mysql状态 配置主从 1.安…

Java 面试题:Java 中接口和抽象类有什么区别

在 Java 编程中,接口(Interface)和抽象类(Abstract Class)是面向对象编程的重要组成部分。它们都提供了一种机制,允许开发者定义抽象的、可以在具体类中实现的行为。然而,接口和抽象类在结构和用…

FreeRTOS简单内核实现5 阻塞延时

文章目录 0、思考与回答0.1、思考一0.2、思考二0.3、思考三 1、创建空闲任务2、实现阻塞延时3、修改任务调度策略4、提供延时时基4.1、SysTick4.2、xPortSysTickHandler( )4.3、xTaskIncrementTick( ) 5、实验5.1、测试5.2、待改进 0、思考与回答 0.1、思考一 为什么 FreeRTO…

C++移动语义

C语言如何实现类似C移动语义 在 C 语言中,没有直接支持移动语义的语法或特性,因为 C 语言相对于 C 来说更为底层,缺乏像 C 那样的语言特性和标准库。然而,你可以通过手动管理内存来实现类似移动语义的效果。 移动语义的主要目的…

Web前端设计工程师:挑战与机遇并存的职业探索

Web前端设计工程师:挑战与机遇并存的职业探索 在数字化浪潮的推动下,Web前端设计工程师成为了互联网行业的核心力量。他们不仅需要掌握深厚的技术功底,还需具备出色的设计思维与创新能力。本文将从四个方面、五个方面、六个方面和七个方面&a…

hbuilderx如何创建html模板

需求:想要将34.html文件的内容作为一个模板,以便后续直接能创建类似内容的html文件 1 首先ctrlc复制模板文件 2 在顶部菜单栏点击 文件 -> 新建 或者使用快捷键 CtrlN 3 在弹出的对话框中选择【自定义模板】 4 将第一步复制的模板文件复制到弹出的文件…

JavaScript 寻找两个数的交集

文章目录 实现思路使用场景考察的知识点实现方法方法 1:使用 filter 和 includes方法 2:使用 Set 和 filter方法 3:使用 reduce方法 4:使用第三方库 数组的交集是指两个数组中都包含的元素集合。即在两个数组中都存在的元素所组成…

Android Studio项目升级报错:Namespace not specified

原项目升级AGP到8.0时报错: Namespace not specified. Specify a namespace in the modules build file: C:\Users\Administrator\Desktop\MyJetpack\app\build.gradle. See https://d.android.com/r/tools/upgrade-assistant/set-namespace for information about…

IT人的拖延——这个任务太复杂,太难了怎么办?

随着科技的发展,IT人需要不断地运用新技术来解决更多传统方式难以解决的问题,有些问题真的不是不想解决,而是真的太复杂,太难了,根本不知道从何开始,也没有什么前辈的经验可以借鉴。我们这些对事情难度的认…

文献越读_细菌中5‘UTR上RG4促进翻译效率

题目:2023_5’UTR G-quadruplex structure enhances translation in size dependent manner 这篇文章的核心内容是关于5’非翻译区(5’UTR)中的G-四链体(G4)结构如何影响细菌翻译效率的研究。以下是文章的主要发现和结…

软链接和硬链接的详解 (Linux系统下)

文章目录 硬链接的引入软链接和硬链接的形成软链接硬链接 软硬链接区别的探究硬链接数结语 硬链接的引入 当我们在命令行中输入ll时会出现很多行信息,详情请看下面的图 ~~~~εεε( ̄▽ ̄) 我在之前的几篇Linux的文章也讲过哦 (o゚v…