信息
· 文章中可能会出现一些错误,希望大佬们可以在评论区指出;
08-模块与包
将所有代码都写进一个文件里会显得十分臃肿,因此需要将不同职能的代码分成各种模块(Module)写到不同的文件中,然后使用Lua语言提供的require()函数读取这些模块,让包(Package)管理这些模块。
导入模块
可以通过require("模块文件名")来读取模块,该函数在初次加载模块时会执行对应模块代码一次,如果模块是用表实现的,可以在它返回表时用局部变量获取它:
local m = require("math")
require()函数的大致执行流程如下:
- 在表
package.loaded中检查模块是否已经被加载,是的话就直接返回对应的值; - 尝试在由
package.path指定的路径中搜索模块,找到了就用loadfile()加载它; - 如果找不到Lua文件,就尝试在由
package.cpath指定的路径中搜索C语言模块,找到了就用package.loadlib()加载它; - 加载模块成功后,将模块的返回值或
true保存在表package.loaded中;
删除模块
根据require()函数的执行流程,要想删除/重新加载指定的模块,需要删除存储在package.loaded中的模块返回值:
package.loaded["模块名"] = nil
package.loaded.模块名 = nil
编写模块
模块通常用表实现,且内部没有全局变量。例如复数模块complex.lua的内容如下:
示例:复数模块 complex.lua点击展开/折叠代码
local M = {}
local function new(r, i)
return { r = r, i = i }
end
local function add(c1, c2)
return new(c1.r + c2.r, c1.i + c2.i)
end
local function sub(c1, c2)
return new(c1.r - c2.r, c1.i - c2.i)
end
local function mul(c1, c2)
return new(c1.r * c2.r - c1.i * c2.i, c1.r * c2.i + c1.i * c2.r)
end
local function inv(c)
local n = c.r ^ 2 + c.i ^ 2
if n == 0 then
error("division by zero complex number")
end
return new(c.r / n, -c.i / n)
end
local function div(c1, c2)
return mul(c1, inv(c2))
end
local function to_string(c)
return string.format("(%g, %g)", c.r, c.i)
end
M.new = new
M.i = new(0, 1)
M.add = add
M.sub = sub
M.mul = mul
M.div = div
M.to_string = to_string
return M
然后在另一个文件中使用require()引用即可:
local C = require("Modules.complex")
local a = C.new(1, 2)
local b = C.new(3, 4)
print(C.to_string(C.add(a, b))) -- > (4, 6)
print(C.to_string(C.mul(a, b))) -- > (-5, 10)
print(C.to_string(C.div(a, b))) -- > (0.44, 0.08)
print(C.to_string(C.mul(C.i, C.i))) -- > (-1, 0) -- 验证 i² = -1
参考资料
- 《Lua程序设计 (第4版)》
- 【唐老狮】Unity热更新之Lua语法