一、模块(module)
模块类似于一个封装库,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。
Lua 的模块是由变量、函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,最后返回这个 table 就行。以下为创建自定义模块 module.lua。
--文件名为module,lua
--定义一个modul的模块
module={}
--定义一个常量
module.var="Lian"
--局部函数,相当于C#中的私有函数,不能在外界调用
local function func1()
print("这是一个局部私有函数")
end
--定义全局一个函数
function module.func2()
func1()
print("这是一个全局公有函数")
end
return module
由上可知,模块的结构就是一个 table 的结构,因此可以像操作调用 table 里的元素那样来操作调用模块里的常量或函数。
上面的 func1 声明为程序块的局部变量,即表示一个私有函数,因此是不能从外部访问模块里的这个私有函数,必须通过模块里的公有函数来调用.
下面再去创建usermodule.lua文件去调用模块中的函数和变量,使用require 函数
Lua提供了一个名为require的函数用来加载模块。要加载一个模块,只需要简单地调用就可以了。
--require "模块名"
m= require "module"
print(m.var)--调用模块中的变量
m.func2()--调用模块中的全局函数
最后运行可以看到输出结果调用了module模块中的函数和变量
运行结果:
Lian
这是一个局部私有函数
这是一个全局公有函数
二、元表(Metatable)
在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作。
因此 Lua 提供了元表(Metatable),允许我们改变table的行为,每个行为关联了对应的元方法。
例如,使用元表我们可以定义Lua如何计算两个table的相加操作a+b。
有两个很重要的函数来处理元表:
setmetatable(table,metatable):
对指定table设置元表(metatable),如果元表(metatable)中存在__metatable键值,setmetatable会失败 。
getmetatable(table): 返回对象的元表(metatable)。
如何对指定的表设置元表:
mytable={"Lua","Java","C","C#","C++"}--普通表
--使用__metatable可以保护元表,禁止用户访问元表中的成员或者修改
mymetatable={__metatable="lock"}--元表 元表扩展了普通表的行为
mytable=setmetatable(mytable,mymetatable)--给指定的表设定元表
print(getmetatable(mytable))--返回普通表的元表
输出结果:lock
__index 元方法
是 metatable 最常用的键。
当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。
如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。
__index 元方法查看表中元素是否存在,如果不存在,返回结果为 nil;如果存在则由 __index 返回结果。
--__index用来处理访问到的索引不存在的时候怎么办
mytable={"Lua","Java","C","C#","C++"}--普通表
mymetatable={
__index=function (tab,key)
return "JavaScript"
end
}--元表 元表扩展了普通表的行为
mytable=setmetatable(mytable,mymetatable)--给指定的表设定元表
print(mytable[10])--访问表中不存在的键时会执行元表中的匿名函数
输出结果:JavaScript
__newindex 元方法
__newindex 元方法用来对表更新,__index则用来对表访问 。
当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。
--__newindex当我们对表的数据进行修改的时候,当我们给表添加新的键值对的时候会起作用
mytable={"Lua","Java","C","C#","C++"}--普通表
mymetatable={
__newindex=function (tab,key,value)
print("我们要修改的key为:"..key.."把这个key值修改为:"..value)
rawset(tab,key,value)--设置键值对,添加输入进来的键值对
end
}--元表 元表扩展了普通表的行为
mytable=setmetatable(mytable,mymetatable)--给指定的表设定元表
mytable[6]="JavaScript"
print(mytable[6])
输出结果:
我们要修改的key为:6把这个key值修改为:JavaScript
JavaScript
为表添加操作符
__add元方法:当两个表相加时实现相应的函数方法
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
}--元表 元表扩展了普通表的行为
mytable=setmetatable(mytable,mymetatable)--给指定的表设定元表
newtab={"PHP","Phthon"}
--其中只要有一个表设置了元表都可以实现加法
v=mytable+newtab
for k,v in pairs(v) do
print(k,v)
end
输出结果:
1 Lua
2 Java
3 C
4 C#
5 C++
6 PHP
7 Phthon
其他操作符:
__call元方法
__call 元方法在 Lua 调用一个值时调用。也就是说当我们把表当作函数来使用的时候调用,例如:mytable(25)
mytable={"Lua","Java","C","C#","C++"}
mymetatable={
__call=function (tab,arg)
print("Call元方法_"..arg)
end
}
mytable=setmetatable(mytable,mymetatable)
mytable("凉")
输出结果:Call元方法_凉
__tostring 元方法
__tostring 元方法用于修改表的输出行为。表示在使用输出print(table)的时候会调用元表中的函数,如下
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)
输出结果:
Lua,Java,C,C#,C++,