1、元表的使用,实现一个面向对象的类
Lua查找表元素的过程
基础学习:Lua面向对象编程 (__index、__newindex、__call、__add)_ccsu_deer-CSDN博客
做法:用__index实现继承
--继承关系
Shape = {area = 0}
function Shape:new(o, side)
o = o or {}
setmetatable(o, self)
self.__index = self --保持继承链,不加此行, t1就没有__index元方法,下面的t2 = t1:new({}, 4)会报错
side = side or 0
o.area = side * side
return o
end
t1 = Shape:new({key1 = 1}, 3)
print("t1.area:", t1.area)
print("t1.key1:", t1.key1)
t2 = t1:new({key2 = 2}, 4)
print("t2.key1:", t2.key1)
print("t2.key2:", t2.key2)
t3 = t2:new({key3 = 3}, 5)
print("t3.key1:", t3.key1)
print("t3.key2:", t3.key2)
print("t3.key3:", t3.key3)
2、元方法的使用
用setmetatable,重载元表里的相关运算函数即可
如:
__add(a, b) 对应表达式 a + b
__sub(a, b) 对应表达式 a - b
__mul(a, b) 对应表达式 a * b
__div(a, b) 对应表达式 a / b
__mod(a, b) 对应表达式 a % b
__pow(a, b) 对应表达式 a ^ b
__unm(a) 对应表达式 -a
__concat(a, b) 对应表达式 a .. b
__len(a) 对应表达式 #a
__eq(a, b) 对应表达式 a == b
__lt(a, b) 对应表达式 a < b
__le(a, b) 对应表达式 a <= b
重载__add例子:
--只读table
t = setmetatable({1, 2, 3},{
__add = function(self, newtable)
len1 = #self
len2 = #newtable
sum = 0
for i=1, len1 do
sum = sum + self[i]
end
for i=1, len2 do
sum = sum + newtable[i]
end
return sum
end
})
t1 = {2,3,4}
answer = t + t1
print("answer:", answer)
3、Lua的GC
三色标记法:深入探究Lua的GC算法_jinxinliu1的专栏-CSDN博客_lua的gc
一、GC的原理及其算法设计
不同的语言,对GC算法的设计不同,常见的GC算法是引用计数和Mark-Sweep算法, c#采用的是Mark-sweep && compact算法, Lua采用的是Mark-sweep算法,分开说一下:
引用计数算法:在一个对象被引用的情况下,将其引用计数加1,反之则减1,如果计数值为0,则在GC的时候回收,这个算法有个问题就是循环引用。
Mark-sweep算法:每次GC的时候,对所有对象进行一次扫描,如果该对象不存在引用,则被回收,反之则保存。
在Lua5.0及其更早的版本中,Lua的GC是一次性不可被打断的过程,使用的Mark算法是双色标记算法(Two color mark),这样系统中对象的非黑即白,要么被引用,要么不被引用,这会带来一个问题:在GC的过程中如果新加入对象,这时候新加入的对象无论怎么设置都会带来问题,如果设置为白色,则如果处于回收阶段,则该对象会在没有遍历其关联对象的情况下被回收;如果标记为黑色,那么没有被扫描就被标记为不可回收,是不正确的。
为了降低一次性回收带来的性能问题以及双色算法的问题,在Lua5.1后,Lua都采用分布回收以及三色增量标记清除算法(Tri-color incremental mark and sweep)
其基本的原理伪代码,参考书中原文为:
每个新创建的对象颜色设置为白色
//初始化阶段
遍历root节点中引用的对象,从白色置为灰色,并且放入到灰色节点列表中
//标记阶段
while(灰色链表中还有未扫描的元素):
从中取出一个对象,将其置为黑色
遍历这个对象关联的其他所有对象:
if 为白色
标记为灰色,加入到灰色链表中(insert to the head)
//回收阶段
遍历所有对象:
if 为白色,
没有被引用的对象,执行回收
else
重新塞入到对象链表中,等待下一轮GC
4、Lua和C++的相互调用
5、setfenv和getfenv
6、热更新的实现和流程
1.对比差异文件
2.下载
3.解压
4.删除旧文件,移动新文件
5.删除多余文件
6.重新加载脚本
1、首次进入app,初始化版本号version=0
2、socket::send()把版本号发送给服务器,进行版本校验
3、服务器版本号校验,如果app版本号与服务器版本号不一致,进行资源列表下载
4、socket::receive() app进行校验,版本资源中,是否已经存在要下载的资源,如果存在,对应的不下载;如果不存在,进行下载。情况二:把本地版本已存在的进行移除,接着进行下载
5、app读取资源,进行资源下载