一、模塊(module)
模塊類似于一個封裝庫,可以把一些公用的代碼放在一個文件里,以 API 接口的形式在其他地方調(diào)用,有利于代碼的重用和降低代碼耦合度。
Lua 的模塊是由變量、函數(shù)等已知元素組成的 table,因此創(chuàng)建一個模塊很簡單,就是創(chuàng)建一個 table,然后把需要導(dǎo)出的常量、函數(shù)放入其中,最后返回這個 table 就行。以下為創(chuàng)建自定義模塊 module.lua。
--文件名為module,lua
--定義一個modul的模塊
module={}
--定義一個常量
module.var="Lian"
--局部函數(shù),相當(dāng)于C#中的私有函數(shù),不能在外界調(diào)用
local function func1()
print("這是一個局部私有函數(shù)")
end
--定義全局一個函數(shù)
function module.func2()
func1()
print("這是一個全局公有函數(shù)")
end
return module
由上可知,模塊的結(jié)構(gòu)就是一個 table 的結(jié)構(gòu),因此可以像操作調(diào)用 table 里的元素那樣來操作調(diào)用模塊里的常量或函數(shù)。
上面的 func1 聲明為程序塊的局部變量,即表示一個私有函數(shù),因此是不能從外部訪問模塊里的這個私有函數(shù),必須通過模塊里的公有函數(shù)來調(diào)用.
下面再去創(chuàng)建usermodule.lua文件去調(diào)用模塊中的函數(shù)和變量,使用require 函數(shù)
Lua提供了一個名為require的函數(shù)用來加載模塊。要加載一個模塊,只需要簡單地調(diào)用就可以了。
--require "模塊名"
m= require "module"
print(m.var)--調(diào)用模塊中的變量
m.func2()--調(diào)用模塊中的全局函數(shù)
最后運(yùn)行可以看到輸出結(jié)果調(diào)用了module模塊中的函數(shù)和變量
運(yùn)行結(jié)果:
Lian
這是一個局部私有函數(shù)
這是一個全局公有函數(shù)
二、元表(Metatable)
在 Lua table 中我們可以訪問對應(yīng)的key來得到value值,但是卻無法對兩個 table 進(jìn)行操作。
因此 Lua 提供了元表(Metatable),允許我們改變table的行為,每個行為關(guān)聯(lián)了對應(yīng)的元方法。
例如,使用元表我們可以定義Lua如何計算兩個table的相加操作a+b。
有兩個很重要的函數(shù)來處理元表:
setmetatable(table,metatable):
對指定table設(shè)置元表(metatable),如果元表(metatable)中存在__metatable鍵值,setmetatable會失敗 。
getmetatable(table): 返回對象的元表(metatable)。
如何對指定的表設(shè)置元表:
mytable={"Lua","Java","C","C#","C++"}--普通表
--使用__metatable可以保護(hù)元表,禁止用戶訪問元表中的成員或者修改
mymetatable={__metatable="lock"}--元表 元表擴(kuò)展了普通表的行為
mytable=setmetatable(mytable,mymetatable)--給指定的表設(shè)定元表
print(getmetatable(mytable))--返回普通表的元表
輸出結(jié)果:lock
__index 元方法
是 metatable 最常用的鍵。
當(dāng)你通過鍵來訪問 table 的時候,如果這個鍵沒有值,那么Lua就會尋找該table的metatable(假定有metatable)中的__index 鍵。如果__index包含一個表格,Lua會在表格中查找相應(yīng)的鍵。
如果__index包含一個函數(shù)的話,Lua就會調(diào)用那個函數(shù),table和鍵會作為參數(shù)傳遞給函數(shù)。
__index 元方法查看表中元素是否存在,如果不存在,返回結(jié)果為 nil;如果存在則由 __index 返回結(jié)果。
--__index用來處理訪問到的索引不存在的時候怎么辦
mytable={"Lua","Java","C","C#","C++"}--普通表
mymetatable={
__index=function (tab,key)
return "JavaScript"
end
}--元表 元表擴(kuò)展了普通表的行為
mytable=setmetatable(mytable,mymetatable)--給指定的表設(shè)定元表
print(mytable[10])--訪問表中不存在的鍵時會執(zhí)行元表中的匿名函數(shù)
輸出結(jié)果:JavaScript
__newindex 元方法
__newindex 元方法用來對表更新,__index則用來對表訪問 。
當(dāng)你給表的一個缺少的索引賦值,解釋器就會查找__newindex 元方法:如果存在則調(diào)用這個函數(shù)而不進(jìn)行賦值操作。
--__newindex當(dāng)我們對表的數(shù)據(jù)進(jìn)行修改的時候,當(dāng)我們給表添加新的鍵值對的時候會起作用
mytable={"Lua","Java","C","C#","C++"}--普通表
mymetatable={
__newindex=function (tab,key,value)
print("我們要修改的key為:"..key.."把這個key值修改為:"..value)
rawset(tab,key,value)--設(shè)置鍵值對,添加輸入進(jìn)來的鍵值對
end
}--元表 元表擴(kuò)展了普通表的行為
mytable=setmetatable(mytable,mymetatable)--給指定的表設(shè)定元表
mytable[6]="JavaScript"
print(mytable[6])
輸出結(jié)果:
我們要修改的key為:6把這個key值修改為:JavaScript
JavaScript
為表添加操作符
__add元方法:當(dāng)兩個表相加時實(shí)現(xiàn)相應(yīng)的函數(shù)方法
mytable={"Lua","Java","C","C#","C++"}--普通表
mymetatable={
--兩表相加將新表中的元素添加到mytable中去
__add=function (tab,newtab)
local mi=0
for k,v in pairs(tab) do
if (k>mi)then
mi=k
end
end
for k,v in pairs(newtab) do
mi=mi+1
table.insert(tab,mi,v)
end
return tab
end
}--元表 元表擴(kuò)展了普通表的行為
mytable=setmetatable(mytable,mymetatable)--給指定的表設(shè)定元表
newtab={"PHP","Phthon"}
--其中只要有一個表設(shè)置了元表都可以實(shí)現(xiàn)加法
v=mytable+newtab
for k,v in pairs(v) do
print(k,v)
end
輸出結(jié)果:
1 Lua
2 Java
3 C
4 C#
5 C++
6 PHP
7 Phthon
其他操作符:

__call元方法
__call 元方法在 Lua 調(diào)用一個值時調(diào)用。也就是說當(dāng)我們把表當(dāng)作函數(shù)來使用的時候調(diào)用,例如:mytable(25)
mytable={"Lua","Java","C","C#","C++"}
mymetatable={
__call=function (tab,arg)
print("Call元方法_"..arg)
end
}
mytable=setmetatable(mytable,mymetatable)
mytable("涼")
輸出結(jié)果:Call元方法_涼
__tostring 元方法
__tostring 元方法用于修改表的輸出行為。表示在使用輸出print(table)的時候會調(diào)用元表中的函數(shù),如下
mytable={"Lua","Java","C","C#","C++"}
mymetatable={
__tostring=function (tab)
local str=""
for k,v in pairs(tab) do
str=str..v..","
end
return str
end
}
mytable=setmetatable(mytable,mymetatable)
print(mytable)
輸出結(jié)果:
Lua,Java,C,C#,C++,