文章目录
目的
在前一篇文章: 《Lua入门使用与基础语法》 中介绍了一些基础的内容。这里将继续介绍Lua一些更多的内容。
同样的本文参考自官方手册:
https://www.lua.org/manual/
错误处理
下面代码可以直接测试相关内容:
-- 使用 assert (v [, message]) 可以检查条件v,如果失败则抛出错误信息message--[[
使用 error (message [, level]) 抛出错误信息message
level为1时(默认值)会在message头部添加调用error函数的位置信息;
level为2时会添加调用error的函数被调用的位置信息;
level为0时不添加额外信息。
]]-- 使用 pcall() (f [, arg1, ···]) 执行函数并捕获可能的错误。执行无错误返回true,否则返回false和错误对象。functionfunc1(arg)error(arg)-- 抛出错误end
ret, msg =pcall(func1,"hello naisu!")print("pcall: ", ret, msg)-- xpcall (f, msgh [, arg1, ···]) 和pcall类似,第二个参数为错误处理函数functionfunc2()print(debug.traceback())end
ret, msg =xpcall(func1, func2,"hello naisu!")print("xpcall: ", ret, msg)
元表和元方法
Lua中可以给值(变量)添加一个原表,元表中可以是各种元方法。元方法用于改变该对象的默认行为,比如该对象运算时的行为,格式化输出时的行为等。
使用
setmetatable (table, metatable)
方法向
table
添加一个
metatable
,
metatable
填
nil
时用于移除元表;使用
getmetatable (object)
返回对象的原表。
常见的运算相关元方法如下:
元方法运算元方法运算元方法运算元方法运算__add+__sub-__mul*__div/__mod%__pow^__unm-__idiv//__band&__bor|__bxor(异或)__bnot(非)__shl<<__shr>>__concat…__len#__eq==__lt<__le<=
除了上面一些基础的运算相关的元方法,Lua中还有更多元方法,下面是个基本的测试:
--[[ 下面是__index ]]print("__index:")
t1 =setmetatable({ a=22},{ __index =function()return33end})print(t1.a)print(t1.b)-- 访问不存在的元素
t2 =setmetatable({ a=22},{ __index ={ b=33}})print(t2.a)print(t2.b)-- 访问不存在的元素print(t2.c)-- 访问不存在的元素--[[ 下面是__newindex ]]print("__newindex:")
t3 =setmetatable({ a=22},{ __newindex =function(table, key, value)print(#table, key, value)end})print(t3.a)
t3.b =33-- 设置不存在的元素时会调用__newindexprint(t3.b)-- __newindex是函数时,值并不会设置到table中
t4 =setmetatable({ a=22},{ __newindex =function(table, key, value)rawset(table, key, value *2)end})print(t4.a)
t4.b =33-- 设置不存在的元素时会调用__newindexprint(t4.b)-- rawset方法将新元素添加到table中
t5 ={}
t6 =setmetatable({ a=22},{ __newindex = t5})
t6.b =33print(t6.b)-- __newindex是表时,设置不存在的元素,值并不会设置到table中print(t5.b)-- __newindex是表时,设置不存在的元素,值会设置到元表中--[[ 下面是__call ]]print("__call:")
t7 =setmetatable({ a=22},{ __call =function(table, value)print(table.a, value)end})t7(33)-- __call方法会在把表当函数用的时候被调用--[[ 下面是__close ]]print("__close:")
t8 =setmetatable({ a=22},{ __close =function(table)print(table.a)end})dolocal var<close>= t8
end-- close属性的变量会在退出其作用域时调用__close方法--[[ 下面是__tostring ]]print("__tostring:")
t9 =setmetatable({ a=22},{ __tostring =function(table)return"value: "..table.a end})print(tostring(t9))-- __tostring方法会在使用tostring函数时被调用
垃圾回收
Lua是带垃圾回收功能的,通常不用手动去控制它,如果有特殊需求的话可以使用
collectgarbage ([opt [, arg]])
方法来手动控制垃圾收集器。比如使用
collectgarbage("collect")
进行一次完整的垃圾回收、使用
collectgarbage("count")
获得Lua占用的内存数据(单位为1024字节)。
另外如果一个表被其他表引用的话,该表不会被回收,可以用过弱表来处理该情况:
t1 ={}setmetatable(t1,{__mode ="k"})-- 设置表的key为弱类型
k1 ={}
t1[k1]=22
k2 ={}
t1[k2]=33
k1 =nil-- 将k1删除,k1引用的那个表只存在于t1,但t1是key弱引用,所以这个表将被GCcollectgarbage()-- 强制执行一次GCfor k, v inpairs(t1)doprint(v)end
协程
Lua中的协程和大多数语言中的协程差不多,提供了一些协程创建、启动、挂起等方法,协程需要主动交出控制权。
coroutine.create (f)
传入函数创建协程返回协程句柄;coroutine.resume (co [, val1, ···])
运行协程,传入协程句柄和参数;成功时返回true和返回值;失败时返回false和错误信息;coroutine.yield (···)
协程主动暂停,输入的参数是传递给resume的返回值;coroutine.close (co)
关闭协程coroutine.wrap (f)
传入函数创建协程返回函数,调用该函数相当于调用resume;coroutine.isyieldable ([co])
coroutine.running ()
返回正在运行的协程加上一个布尔值,当正在运行的协程是主协程时为true。coroutine.status (co)
下面代码是个简单的测试:
functionfunc()print("协同程序 func 开始执行")local value = coroutine.yield("暂停 func 的执行")print("协同程序 func 恢复执行,传入的值为: "..tostring(value))print("协同程序 func 结束执行")end-- 创建协同程序local co = coroutine.create(func)-- 启动协同程序local status, result = coroutine.resume(co)print(result)-- 输出: 暂停 func 的执行-- 恢复协同程序的执行,并传入一个值
status, result = coroutine.resume(co,233)print(result)-- 输出: 协同程序 func 恢复执行,传入的值为: 233
模块
当需要多个文件组合实现功能时就涉及到模块的概念的,简单理解就是一个文件引用其他文件:
面向对象
Lua也支持面向对象的方式,本质其实就是table中同时放变量和函数等。稍稍比table使用多一点的内容是可以使用
:
来定义个使用table中的函数,这样这个函数内部默认会有一个指向自身的
self
对象。
下面代码可以直接测试相关内容:
Class ={}function Class:new(name)-- 注意这里内部的操作,这个方法相当于构造函数
obj ={}setmetatable(obj,self)
self.__index = self
self.name = name
return obj
endfunction Class:printName()print(self.name);end
obj1 = Class:new("naisu")-- 新建一个对象print(obj1.name)-- 使用 . 访问属性
obj1:printName()-- 使用 : 调用方法
obj2 = Class:new("nx233")
obj2:printName()
总结
上面的一些Lua的语法功能使得Lua更加灵活和完善,不单单作为脚本,进行大型项目开发也可一用。
版权归原作者 Naisu Xu 所有, 如有侵权,请联系我们删除。