Lua 中的模塊與庫的概念相似,每個(gè)模塊都有一個(gè)全局唯一名字,并且每個(gè)模塊都包含一個(gè)表。使用一個(gè)模塊時(shí),可以使用 require 加載模塊。模塊中可以包括函數(shù)和變量,所有這些函數(shù)和變量被表存儲(chǔ)于模塊的表中。模塊中的表的功能類似于命名空間,用于隔離不同模塊中的相同的變量名。在使用模塊的時(shí)候,我們應(yīng)該遵守模塊定義的規(guī)范,在 require 加載模塊時(shí)返回模塊中的包含函數(shù)和變量的表對(duì)象。
模塊中表的使用使得我們可在絕大多數(shù)情況下可以像操作其它表一樣操作模塊。由于 Lua 語言允許對(duì)模塊本身進(jìn)行操作,所以 Lua 也就具備了許多其它語言需要特殊機(jī)制才能實(shí)現(xiàn)的特殊性質(zhì)。例如,這種自由的表操作機(jī)制使得編程人員可以用多種方法調(diào)用模塊中的函數(shù)。下面的例子演示了其中的一些方法:
-- 假設(shè)我們有一個(gè)板塊 printFormatter
-- 該模塊有一個(gè)函數(shù) simpleFormat(arg)
-- 方法 1
require "printFormatter"
printFormatter.simpleFormat("test")
-- 方法 2
local formatter = require "printFormatter"
formatter.simpleFormat("test")
-- 方法 3
require "printFormatter"
local formatterFunction = printFormatter.simpleFormat
formatterFunction("test")
從上面的例子中可以看出,Lua 不需要任何額外的代碼就可以實(shí)現(xiàn)非常靈活的編程技巧。
Lua 提供了一個(gè)高層次抽象的函數(shù) require,使用這個(gè)函數(shù)可以加載所有需要的模塊。在設(shè)計(jì)之初,這個(gè)函數(shù)就被設(shè)計(jì)的盡可能的簡(jiǎn)單,以避免加載模塊時(shí)需要太多的模塊信息。require 函數(shù)加載模塊時(shí)把所有模塊都只當(dāng)作一段定義了變量的代碼(事實(shí)上是一些函數(shù)或者包含函數(shù)的表)而已,完全不需要更多的模塊信息。
讓我們看一下面這個(gè)例子。在這個(gè)例子中,我們定義了模塊 mymath,在這個(gè)模塊中定義一些數(shù)學(xué)函數(shù),并將該模塊存儲(chǔ)于 mymath.lua 文件中。具體內(nèi)容如下:
local mymath = {}
function mymath.add(a,b)
print(a+b)
end
function mymath.sub(a,b)
print(a-b)
end
function mymath.mul(a,b)
print(a*b)
end
function mymath.div(a,b)
print(a/b)
end
return mymath
接下來,我們?cè)诹硪粋€(gè)文件 moduletutorial.lua 文件中訪問這個(gè)模塊。具體代碼如下所示:
mymathmodule = require("mymath")
mymathmodule.add(10,20)
mymathmodule.sub(30,20)
mymathmodule.mul(10,20)
mymathmodule.div(30,20)
運(yùn)行這段代碼這前,我們需要將兩個(gè) lua 源代碼文件放在同一目錄下,或者把模塊代碼文件放在包路徑下(這種情況需要額外的配置)。運(yùn)行上面的代碼,可以得到如下的輸出結(jié)果:
30
10
200
1.5
下面,我們將用 package.seall 這種比較老的方法重新實(shí)現(xiàn)上面的例子。這種實(shí)現(xiàn)方法主要用于 Lua 5.1 或 5.2 版本。使用這種方式實(shí)現(xiàn)模塊的代碼如下所示:
module("mymath", package.seeall)
function mymath.add(a,b)
print(a+b)
end
function mymath.sub(a,b)
print(a-b)
end
function mymath.mul(a,b)
print(a*b)
end
function mymath.div(a,b)
print(a/b)
end
使用此模塊的代碼如下所示:
require("mymath")
mymath.add(10,20)
mymath.sub(30,20)
mymath.mul(10,20)
mymath.div(30,20)
當(dāng)我們運(yùn)行這段代碼,我們會(huì)得到與前面相同的輸出結(jié)果。但是建議你不要使用這種方式,因?yàn)槠毡檎J(rèn)為這種方式不及新的方法安全。許多用到 Lua 語言的 SDK 都已經(jīng)不再使用這種方式定義模塊,例如, Corna SDK。