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