Lua模块与包

模块类似于一个封装库

创建方法:

  • 创建一个table
  • 把需要导出的常量、函数放入其中
  • 返回该table
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

-- 定义一个名为mymodule的模块
mymodule={}

-- 定义一个常量
mymodule.constant="这是一个常量"

-- 定义一个函数
function ()
io.write("这是一个公有函数!n")
end

local function func2()
print("这是一个私有函数!")
end

function module.func3()
func2()
end

return mymodule

require函数

1
2
3
4
5
6
7
8
9
10
11
12
13
-- require函数用于加载模块,使用方法:
require("mymodule")
require "mymodule"

-- 执行require后返回由模块常量或函数组成的table,并且还会定义一个包含该table的全局变量
require("mymodule")
print(module.constant)
mymodule.func3()

-- 也可以创建别名
local m=require("mymodule")
print(m.constant)
m.func3()

加载机制:

https://www.runoob.com/lua/lua-modules-packages.html

Metatable(元表)

元表允许改变table的行为,每个行为关联了对应的元方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
--[[
作用:对指定的table设置metatable
参数列表:
table:操作对象
metatable:元表
返回值:绑定好对象的table
]]
setmetatable(table,metatable)

--[[
作用:返回对象的元表
参数列表:
table:操作对象
返回值:元表
]]
getmetatable(table)

__index元方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-- 当使用table中的某个键key时,会查找table中的该键key,如果没有这个键key则会寻找该table的metatable中的_index键,如果__index包含一个table,Lua会在表格中查找键值为key的元素
other={foo=3}
t=setmetatable({},{_index=other}) -- t中没有foo键,调用foo是在metatable中查找__index对应的table,再在该table上查找foo键
t.foo -- 输出:3

-- __index 元方法查看表中元素是否存在,如果不存在,返回结果为 nil;如果存在则由 __index 返回结果。如果__index包含一个函数,Lua就会调用该函数,table和键作为参数传递给函数。
mytable=setmetatable({key1="value1"},{
__index=function(mytable,key)
if key == "key2" then
return "metatablevalue"
else
return nil
end
end
})

print(mytable.key1,mytable.key2)
--[[
输出结果:
value1 metatablevalue
]]

Lua查找table元素规则:

  1. 在表中查找,如果找到,返回该元素,找不到则继续

  2. 判断该表是否有元表,如果没有元表,返回 nil,有元表则继续

  3. 判断元表有没有__index方法,如果__index方法为nil,返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值

__newindex元方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
-- __newindex方法用于对表更新,__index则用来对表访问
-- 给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作
mymetatable={}
mytable=setmetatable({key1="value1"},{__newindex=mymetatable})
print(mytable.key1)
mytable.newkey="新值2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)
--[[
输出结果:
value1
nil 新值2
新值1 nil
]]

-- 如果__newindex元方法是一个函数,则会把该table,该key,该value作为参数传进函数
mytable = setmetatable({key1 = "value1"}, {
__newindex = function(mytable, key, value)
rawset(mytable, key, """..value..""")
end
})
mytable.key1 = "new value"
mytable.key2 = 4
print(mytable.key1,mytable.key2)
--[[
输出结果:
new value "4"
]]

为表添加操作符(类似于运算符重载)

元方法 对应运算符
__add +
__sub -(减号)
__mul *
__div /
__mod %
_unm -(负号)
__concat ..
__eq ==
__lt <
__le <=

__call元方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- __call元方法在该表被当成函数来调用时会调用
mytable=setmetatable({10},{
__call=function(mytable,newtable)
local sum=0
for i=1,#mytable do
sum=sum+mytable[i]
end
for i=1,#newtable do
sum=sum+newtable[i]
end
return sum
end
})
newtable={10,20,30}
print(mytable(newtable)) -- 输出结果:70

__tostring元方法

1
2
3
4
5
6
7
8
9
10
11
-- __tostring 元方法用于修改表的输出行为
mytable = setmetatable({ 10, 20, 30 }, {
__tostring = function(mytable)
local sum = 0
for k, v in pairs(mytable) do
sum = sum + v
end
return "表所有元素的和为 " .. sum
end
})
print(mytable) -- 输出结果:表所有元素的和为 60