Lua 面经
Lua特性
- 轻量级:用C语言编写,编译后仅仅一百余K
- 可扩展:提供了非常易于使用的扩展接口和机制
- 支持面向过程(procedure-oriented)编程和函数式编程(functional programming)
- 自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象
Lua数据类型
数据类型 | nil | boolean | number | string | table | userdata | function | thread |
Lua 把 false 和 nil 看作是"假",其他的都为"真":
pairs 和 ipairs区别
- pairs: 迭代 table,可以遍历表中所有的 key, 可以返回 nil
- ipairs: 迭代数组,不能返回 nil,如果遇到 nil 则退出
Lua怎么实现面向对象
面对对象是基于元表metatable,元方法__index来实现的。如果访问了lua表中不存在的元素时,就会触发lua的一套查找机制,也是凭借这个机制,才能够实现面向对象的。
元表(metatable):允许我们改变table的行为,每个行为关联了对应的元方法。当Lua试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫"__add"的字段,若找到,则调用对应的值。
元方法(__index):当通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。
- 封装:在Lua中的类,其实都是table,因为table既可以存储普通变量又可以存储函数或者另一个table,利用这个特性,我们实现了面向对象的类中的方法、属性(字段)和构造方法
- 继承:SubClass的instance,如果在SubClass中找不到的属性和方法,将会去其元表Class(父类)的__index中查找,找到即可调用,实现了继承父类特性
- 多态:由于__index的查找特性,实例会在自己的__index中查找属性和方法,找到即可调用,不会再继续去父类中 查找,即实现了函数覆盖(C++覆盖定义:总与多态绑定在一起,覆盖发生在派生类与基类之间,两个函数必须完全相 同,且都是虚函数)功能,即多态。
Lua查找一个表元素时的规则
- 在表中查找,如果找到,返回该元素,找不到则继续
- 判断该表是否有元表,如果没有元表,返回nil,有元表则继续。
- 判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值。
Lua闭包
定义:通过调用含有一个内部函数加上该外部函数持有的外部局部变量(upvalue)的外部函数(就是工厂)产生的一个实例函数
组成:外部函数+外部函数创建的upvalue(引用外包函数的局部变量,在Lua中,函数参数也是局部变量)+内部函数(闭包函数)
闭包在迭代器中的运用:迭代器需要保留上一次调用的状态和下一次成功调用的状态。
Lua弱引用table
Lua有自己的garbage collection,会自动删除过期的对象。垃圾收集器只能回收那些它认为是垃圾的东西,不会回收那些用户认为是垃圾的东西。
- 比如那些存储在全局变量中的对象,即使程序不会再用到它们,但对于Lua来说它们也不是垃圾,除非用户将这些对象赋值为nil,这样它们才能被释放。
- 将一个对象放在一个数组中时,它就无法被回收,这是因为即使当前没有其他地方在使用它,但数组仍引用着它,除非用户告诉Lua这项引用不应该阻碍此对象的回收,否则Lua是无从得知的。
弱引用table就是用户告诉lua一个引用不应该阻止该对象的回收,通过其元表中的__mode字段来决定的
- 具有弱引用key的table;
- 具有弱引用value的table;
- 同时具有弱引用key和value的table;
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | a = {1, name= 'cq' } setmetatable(a, {__mode= 'k' }) -- 这个table的key是弱引用的 key = {} a[key] = 'key1' key = {} a[key] = 'key2' print( "before GC" ) for k, v in pairs(a) do print(k, '\t' , v) end collectgarbage() print( "\nafter GC" ) for k, v in pairs(a) do print(k, '\t' , v) ends |
输出:第二句赋值key={}会覆盖第一个key,当收集器运行时,由于没有地方在引用第一个key,因此第一个key就被回收了,并且table中的相应条目也被删除了。至于第二个key,变量key仍引用着它,因此它没有被回收。
1 2 3 4 5 6 7 8 9 10 | before GC 1 1 table: 0x167ba70 key1 name cq table: 0x167bac0 key2 after GC 1 1 name cq table: 0x167bac0 key2 |
Reference:
- https://www.cnblogs.com/jiahuafu/p/9389954.html
- https://www.cnblogs.com/chenny7/p/4050259.html
__EOF__

本文链接:https://www.cnblogs.com/cancantrbl/p/13854919.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现