Lua元表

        哈喽,好久没有做记录了,最近刚好有时间打算整理一些基础常用内容,先做一期关于Lua相关的内容热热身。如果内容有误,欢迎大家指出我会积极做出响应。

        在Lua中,元表(metatable) 和 元方法(metamethod) 是一对密切相关的概念,用于扩展表的行为。元表是一个特殊的表,用来定义元方法,而元方法则是元表中的某些特定字段,用于自定义表的操作行为,这一章主要记录元表(metatable)。

1. 什么是Lua

  • 在开始介绍元表之前,我们先大致了解Lua是什么。
  1. Lua 是一种可嵌入、轻量、快速、功能强大的脚本语言。
  2. Lua 很适合用于配置、脚本化、插件化和快速构造原型的场景。
  3. Lua 是一门轻量级脚本语言,其核心设计目标之一是简单而高效。
  4. Lua 体积小、启动速度快,在所有脚本引擎中,Lua 的速可以于说是最快的。
  5. Lua 运行依托于宿主语言可以是c++,c#,golang等,只需要实现Lua解释器。

2. Lua的元表

   Lua中设计 元表 的主要原因是为了提供一种灵活的机制。

   元表 像是一个“操作指南”,里面包含了一系列的解决方案。

  • 元表 能够扩展表的行为,而无需改变Lua本身的简单性和动态性。
  • 元表 是 Lua 中的普通表,可以附加到另一个表上,用于改变该表的行为。
  • 元表 赋予了Lua用户自定义操作的能力,如重载操作符,拦截访问,模拟面向对象编程等。

        例如,当对一个表执行特定操作(如算术运算、比较操作或访问不存在的键)时,Lua 会检查是否有 元表 以及是否定义了对应的 元方法

2.1 设置元表

   通过 setmetatablegetmetatable 可以设置和获取表的元表。

local t = {}           -- 普通表
local mt = {}          -- 元表
setmetatable(t, mt)    -- 将元表附加到表 t 上print(getmetatable(t)) -- 输出元表 mt
  • 每个表可以有一个独立的元表。

  • 轻量灵活:元表是普通的表,但它的字段有特殊的意义(元方法)。

  • 动态行为扩展:元表提供了一种机制,可以在不改变表本身的情况下扩展表的行为。

2.2 原始元表

  • Lua中元表的设置只能针对table,其他类型都不能设置。

  • Lua只有string初始化了元表,而且是针对所有的字符串,其他的类型都为nil。

  • table的原始元表为nil,也就是没有设置元表,只能通过 setmetatable 进行设置。

  • 多个table可以共享一个table作为元表,也可以使用自己作为自己的元表,它自身也是table。

print("表的初始值", getmetatable({}))           --> 表的初始值	nilprint("整型的初始值", getmetatable(10))         --> 整型的初始值	nil
print("浮点型的初始值", getmetatable(10.0))      --> 浮点型的初始值	nil--- 通过打印可以看到两个字符串的元表是同一个
print("字符串的初始值", getmetatable("新年快乐"))   --> 字符串的初始值	table: 0x600000b14640
print("字符串的初始值", getmetatable("Happy New Year"))  --> 字符串的初始值	table: 0x600000b14640print("布尔型的初始值", getmetatable(true))     --> 布尔型的初始值	nilprint("nil的初始值", getmetatable(nil))         --> nil的初始值	nilfunction sayHello()  end
print("函数的初始值", getmetatable(sayHello))   --> 函数的初始值	nil

2.3 setmetatable 

  • 为表设置一个元表。元表是一个特殊的表,可以用来扩展和改变 Lua 表的行为。

  • 参数:

    • table:需要设置元表的目标表。

    • matetable:元表,要设置的元表,可以包含元方法(如 __index__add 等)。

  • 返回值:返回被设置元表的表,也就是参数table。

  • 给表设置元表 

local t = {}  -- 原始表
local mt = {} -- 元表setmetatable(t, mt) -- 设置元表
print(getmetatable(t) == mt) -- 输出 true
  • 设置操作符重载 

    • 通过设置元表中的元方法,扩展表的行为。

local t1 = {value = 10}
local t2 = {value = 20}
local mt = {__add = function(a, b)return {value = a.value + b.value}end
}setmetatable(t1, mt)
setmetatable(t2, mt)local t3 = t1 + t2
print(t3.value) -- 输出 30
  •  结合 __index 实现继承

    • setmetatable 常用于为表设置 __index 元方法,来实现默认值或继承。

local defaults = {name = "Default", age = 0}
local t = {}local mt = {__index = defaults
}setmetatable(t, mt)print(t.name) -- 输出 "Default"
print(t.age)  -- 输出 0
  •  注意事项

    • 只能为表设置元表,如果为非表类型设置元表,将会报错。

    • 同一个表只能有一个元表,之后调用 setmetatable 会覆盖之前的元表。

 2.4 getmetatable

  • 获取表的元表。

  • 如果表没有元表,或元表中设置了保护(__metatable),则返回 nil 或保护值。

  • 参数:

    • table:需要获取元表的目标表。

  • 返回值:

    • 如果表有元表,返回元表。

    • 如果没有元表,返回 nil

    • 如果元表设置了 __metatable 字段,则返回该字段的值,而不是元表本身。

  • 获取表的元表 

local t = {}
local mt = {}setmetatable(t, mt)local retrieved = getmetatable(t)
print(retrieved == mt) -- 输出 true
  • 保护元表

    • 通过在元表中设置 __metatable 字段,可以防止外部获取或修改元表。 

local t = {}
local mt = {}
setmetatable(t, mt)mt.__metatable = "Protected"print(getmetatable(t)) -- 输出 "Protected"-- 尝试修改元表会报错
-- setmetatable(t, nil) -- 报错:cannot change protected metatable

2.5 setmetatable 与 getmetatable 的关系

  • setmetatable 用于设置元表。

  • getmetatable 用于获取元表。

  • 两者通常一起使用,用于实现自定义行为。例如: 

local t = {}
local mt = {__index = function(_, key)return "default value for " .. keyend
}setmetatable(t, mt)
print(getmetatable(t)) -- 输出元表 mtprint(t.foo) -- 输出 "default value for foo"

        以上基本就是Lua元表的相关介绍,下一章我会准备详细记录下与 元表 配合使用的 元方法。如果以上内容有偏差的地方欢迎各位大佬留言指出。

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

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

相关文章

香橙派5Plus启动报错bug: spinlock bad magic on cpu#6, systemd-udevd/443

一、问题 如图: 接上调试串口,每次启动都会报错。不过使用过程中没有发现有什么影响。 百度查阅,有一位博主提到,但是没有细说解决方案: spinlock变量没有初始化_spinlock bad magic on-CSDN博客https://blog.csdn.n…

多语言宿舍管理:宿舍管理系统的国际化

2.1 Java语言 Java语言是目前最流行的语言之一,不仅可以做桌面窗口形式的程序,还可以做浏览器访问的程序,目前最流行的就是用Java语言作为基础,做各种程序的后台处理。Java语言是操作变量的语言,而变量则是Java对于数据…

【Docker命令】如何使用`docker exec`在容器内执行命令

大家好,今天我们来聊聊Docker容器管理中的一个非常有用的命令:docker exec。在日常工作中,我们经常需要在运行中的Docker容器内执行各种命令,docker exec正是帮助我们实现这一需求的利器。下面我将通过一个简单的例子,…

FPGA自学之路:到底有多崎岖?

FPGA,即现场可编程门阵列,被誉为硬件世界的“瑞士军刀”,其灵活性和可编程性让无数开发者为之倾倒。但谈及FPGA的学习难度,不少人望而却步。那么,FPGA自学之路到底有多崎岖呢? 几座大山那么高?…

【KLEE】源码阅读笔记----KLEE执行流程

本文架构 1. 动机2.KLEE简介3.KLEE的代码工程结构4. 从KLEE主函数入手main函数step1: 初始化step2:加载.bc文件进行符号执行 读取测试用例输出日志信息 1. 动机 最近准备对KLEE进行修改使其符合我的需要,因此免不了需要对源码进行修改。读懂源码是对在其…

CS 144 check7: putting it all together

Exercises 经验:两边的TCP连接建立得尽快,如果服务器端启动了,客户端没有紧接着启动就连不上。 这是什么神奇的bug呢? 和我之前给域控刷SOC的版本一样。如果域控启动了,在我本地的电脑没有马上和域控的SOC通上信&…

2024年12月CCF-GESP编程能力等级认证Scratch图形化编程二级真题解析

本文收录于《Scratch等级认证CCF-GESP图形化真题解析》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 一、单选题(共 10 题,每题 3 分,共 30 分) 第 1 题 2024 年 10 月 8 日,诺贝尔物理学奖“意外地”颁给了两位计算机科学家约翰霍普菲尔德(John J. Hopfie…

Suno Api V4模型无水印开发「综合实战开发自己的音乐网站」 —— 「Suno Api系列」第14篇

历史文章 Suno AI API接入 - 将AI音乐接入到自己的产品中,支持120并发任务 Suno Api V4模型无水印开发「灵感模式」 —— 「Suno Api系列」第1篇 Suno Api V4模型无水印开发「自定义模式」 —— 「Suno Api系列」第2篇 Suno Api V4模型无水印开发「AI生成歌词」…

服务器压力测试怎么做

在部署任何Web应用程序或服务之前,进行服务器压力测试(也称为负载测试)是确保系统能够处理预期用户流量的关键步骤。通过模拟大量并发请求,可以评估服务器的性能、稳定性和响应时间,识别潜在瓶颈,并优化资源…

PHP之伪协议

文章目录 PHP伪协议php://协议data://协议file://协议phar://协议zip:// & bzip2:// & zlib://协议 过滤器 题目练习[BJDCTF 2020]ZJCTF,不过如此BaseCTF[week1]Aura酱的礼物 PHP伪协议 file:// — 访问本地文件系统 http:// — 访问 HTTP(s) 网址 ftp:// …

linux驱动:6ull(4)初看设备树文件

目录 设备树存放路径 编译dts方法 属性 添加节点例子 在已经添加的节点上外加属性例子 linux内核匹配设备步骤 结合下面这个文章看 linux驱动:(16)在设备树添加自定义节点_linux设备树自定义字段-CSDN博客 设备树存放路径 在linux源码…

【物联网技术与应用】实验15:电位器传感器实验

实验15 电位器传感器实验 【实验介绍】 电位器可以帮助控制Arduino板上的LED闪烁的时间间隔。 【实验组件】 ● Arduino Uno主板* 1 ● 电位器模块* 1 ● USB电缆*1 ● 面包板* 1 ● 9V方型电池* 1 ● 跳线若干 【实验原理】 模拟电位器是模拟电子元件,模…

【YOLO】(基础篇一)YOLO介绍

YOLO YOLO(You Only Look Once)是一种用于实时物体检测的算法,由Joseph Redmon等人提出。它能够同时进行物体分类和定位,并且因其速度和效率而广受赞誉。 工作原理 假设我们要对这张猫的图片完成目标检测,需要框选出…

K8S 黑魔法之如何从 Pod 拿到节点的命令行

搞 K8S 运维的时候,偶尔会遇到一个难题,定位到问题出在某个节点上,而由于权限审批,错误配置等等各种原因,没有办法拿到节点的 SSH 权限,无法进入节点命令行进一步排障。 这个时候,就可以用这个…

Linux-----进程处理(文件IO资源使用)

下面代码是通过父进程和子进程对同一个文件IO资源进行操作,父进程和子进程都对这个进程进行写入操作,我们都知道这两个进程实际上是并发的,所以需要一个同步机制来去操作同一个资源(后面再深入去说明同步的api,这里使用…

golang标准库SSH操作示例

文章目录 前言一、了解SSH二、重要知识点1.安装ssh库2.ssh库重要知识牢记 三、模拟连接远程服务器并执行命令四、SSH与os/exec标准库下执行命令的几种方式对比五、SSH库下三种执行命令方式演示5.1. session.CombinedOutput()示例5.2. session.Run()示例5.3. session.Start()、s…

Pion WebRTC 项目教程

Pion WebRTC 项目教程 webrtc Pure Go implementation of the WebRTC API [这里是图片001] 项目地址: https://gitcode.com/gh_mirrors/we/webrtc 1. 项目目录结构及介绍 Pion WebRTC 项目的目录结构如下: pion/webrtc ├── api ├── examples ├── inter…

替代传统FTP传输,镭速大数据传输系统实现安全高效数据流转!

信息技术的快速进步让大数据成为了企业决策的关键支撑,但同时也带来了巨大的挑战。企业在运营过程中产生的数据量急剧增加,这对数据传输的速度、安全性和效率提出了更高的要求。然而,传统的FTP传输方式在处理大规模数据时显得力不从心&#x…

Java操作Xml

一、数据准备 1、文件头实体类 package com.xiaobai.xmlpractice;import lombok.AllArgsConstructor; import lombok.Data;/*** Author 王天文* Date 2024/12/18 21:46* Description: xml头*/ AllArgsConstructor Data public class Head {private String desc;private Strin…

MyBatis如何处理延迟加载?

大家好,我是锋哥。今天分享关于【MyBatis如何处理延迟加载?】面试题。希望对大家有帮助; MyBatis如何处理延迟加载? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 MyBatis 支持 延迟加载(Lazy Loading&am…