Lua 模塊的基本概念
Lua 中的模塊是一個由函數、變量組成的代碼庫,通常保存在獨立的 .lua
文件中。模塊通過 return
語句導出其內容,供其他腳本調用。模塊化設計可以提高代碼復用性,便于管理。
創建模塊
模塊通常以 .lua
文件形式存在,文件內通過 return
返回一個表(table),表中包含模塊的公開函數或變量。例如:
-- 文件名為 mymodule.lua
local M = {} -- 模塊表function M.add(a, b)return a + b
endfunction M.sub(a, b)return a - b
endreturn M -- 導出模塊
加載模塊
Lua 5.1 及以上版本使用 require
函數加載模塊。require
會搜索模塊路徑并執行文件,返回模塊導出的內容:
local mymodule = require("mymodule") -- 加載模塊
print(mymodule.add(1, 2)) -- 調用模塊函數
模塊搜索路徑
require
通過 package.path
和 package.cpath
確定搜索路徑。package.path
用于 .lua
文件,package.cpath
用于二進制模塊(如 .dll
或 .so
)。默認路徑包含當前目錄和 Lua 安裝路徑。
print(package.path) -- 查看 Lua 模塊搜索路徑
print(package.cpath) -- 查看二進制模塊搜索路徑
模塊的局部變量
模塊中未暴露的局部變量對外不可見,實現封裝:
local M = {}
local privateVar = 100 -- 局部變量,外部不可訪問function M.getPrivate()return privateVar
endreturn M
包管理工具
Lua 的包管理工具如 LuaRocks 可以安裝和管理第三方模塊。安裝命令示例:
luarocks install luasocket
模塊的緩存機制
require
會緩存已加載的模塊,避免重復加載。可以通過 package.loaded
查看或清除緩存:
package.loaded["mymodule"] = nil -- 清除模塊緩存
require("mymodule") -- 重新加載
使用環境隔離
模塊可以通過設置 _ENV
實現沙盒環境,避免污染全局命名空間:
local M = {}
setmetatable(M, { __index = _G }) -- 繼承全局環境
_ENV = M -- 切換環境function add(a, b)return a + b
endreturn M
模塊的依賴管理
模塊可以依賴其他模塊,通過 require
引入:
local json = require("dkjson") -- 引入第三方 JSON 模塊
local M = {}function M.toJson(t)return json.encode(t)
endreturn M
動態加載模塊
loadfile
或 dofile
可以動態加載模塊,但不推薦替代 require
:
local chunk = loadfile("mymodule.lua") -- 加載但不執行
local M = chunk() -- 執行并獲取模塊
模塊的命名規范
Lua 模塊通常使用小寫字母和下劃線命名,如 my_module.lua
。避免與 Lua 關鍵字沖突。
模塊的版本控制
在模塊中定義版本號,便于管理:
local M = {}
M._VERSION = "1.0.0"
return M
模塊的測試與調試
模塊可以通過獨立的測試腳本驗證功能:
local mymodule = require("mymodule")
assert(mymodule.add(1, 2) == 3)
Lua 5.2 后的模塊變化
Lua 5.2 移除了 module
函數,推薦直接使用 return table
的方式定義模塊。
模塊的打包與分發
將模塊打包為 .rocks
文件或直接發布源碼,便于其他開發者使用。LuaRocks 支持模塊發布:
luarocks pack mymodule
模塊的跨平臺兼容性
確保模塊代碼兼容不同操作系統,避免路徑硬編碼:
local path_sep = package.config:sub(1,1) -- 獲取系統路徑分隔符
local path = "foo" .. path_sep .. "bar.lua"
模塊的元表應用
通過元表為模塊添加默認方法或重載操作符:
local M = {}
setmetatable(M, {__add = function(a, b) return a.value + b.value end
})
M.value = 10
return M