接着lua的使用,迭代器、模块和元表,元表为重点需要关注的内容
一、迭代器
pairs就是一个迭代器,它的返回值是key和value,下面自定义一个迭代器
定义迭代器语法:
function 迭代器名
(终止值参数
,初始值参数
)
end
使用迭代器语法:
for 第一个返回值
,第二个返回值
in 迭代器名
,终止值
,初始值
do
end
-- 第一个参数:终止值 第二个参数:初始值
function double(max,init)
if(init < max) then
init = init + 1
return init,init*2
end
end
-- in后面,跟上迭代器名,终止值,初始值
for i,d in double,10,0 do
print(i,d)
end
运行结果:
二、模块
lua5.1开始支持模块,可以将函数封装进模块中,在别的脚本中引用模块
1. 新建模块
-- 定义模块
module = {}
-- 模块的常量
module.name = '我的模块'
module.time = '2022'
-- 对外公开的方法 使用module.方法名定义
function module.func1()
print("func1")
end
-- 内部方法,不能加moudle.
local function func2()
print("func2")
end
function module.func3()
func2()
end
-- 返回模块
return module
2. 其他脚本引入模块
-- 引入模块
require("module")
print(module.name..module.time)
print(module.func1())
print(module.func3())
运行结果:
三、元表
元表允许改变table的行为,对table变相的进行扩展,甚至能达到模拟类的功能
1. 元表定义和使用
元表和table一样,使用{}
定义,使用元表需要和普通表进行结合,调用setmetatable方法
a = {1,2,3} -- 普通表
b = {} -- 元表
c = setmetatable(a,b)
print("table:",a)
print("metatable:",b)
print("ret:",c)
print("getmetatable:",getmetatable(c))
运行结果:
可以发现setmetatable
的返回值为普通表,getmetattable
的返回值为元表
2. index元方法
index元方法定义方式为{__index = 值
},有两种用途
2.1 结合两张普通表
-- 两张普通表
e = {'a','b'}
f = {c = 'c'}
-- 元表将index元方法赋值为f
g = {__index = f}
-- 为e表设置元表
setmetatable(e,g)
print(e['c'])
运行结果:
2.2 扩展没有对应key的取值方法
-- 普通表
e = {'a','b'}
-- 元表将index元方法赋值为一个函数
g = {
__index = function(tab,key)
if(key[tab] == nil) then
return 'null'
end
end
}
-- 为e表设置元表
setmetatable(e,g)
print(e['c'])
print(e[1])
运行结果:
3. newindex元方法
newindex元方法定义方式为{__newindex = 值
},也有两种用途
3.1 将新元素存入另一张普通表中
-- 两张普通表
e = {'a','b'}
f = {}
-- 元表将newindex元方法赋值为f
g = {__newindex = f}
-- 为e表设置元表
setmetatable(e,g)
-- 设置新元素
e[5] = 'f'
print(e[5])
print(f[5])
运行结果:
3.2 扩展插入新元素方法
-- 普通表
e = {'a','b'}
-- 元表将newindex元方法赋值为匿名函数
g = {
__newindex = function(tab,key,val)
print("新key:"..key,"新value:"..val)
rawset(tab,key,val)
end
}
-- 为e表设置元表
setmetatable(e,g)
e['a'] = 'hello'
print(e['a'])
运行结果:
4. 运算符重载
元表的运算符重载使用如下方式定义:
方式 | 对应运算符 |
---|---|
__add | + |
__sub | - |
__mul | * |
__div | / |
__mod | % |
__concat | .. |
__eq | == |
__lt | < |
__le | <= |
__gt | > |
__ge | >= |
测试,合并两个table:
-- 运算符重载
a = {'a','b'}
b = {'c','d'}
c = {
__add = function(tab1,tab2)
-- 获取第一个table的长度
local t1_len = #tab1
-- 遍历第二个table
for k,v in pairs(tab2) do
t1_len = t1_len + 1
-- 将第二个tab的值赋值给第一个tab
tab1[t1_len] = v
end
return tab1
end
}
setmetatable(a,c)
a = a + b
for k,v in pairs(a) do
print(v)
end
运行结果:
5. call元方法
当表被当成函数调用时,会触发
-- call元方法
a = {1,2}
c = {
__call = function(tab,...)
for k,v in pairs({...}) do
print(k,v)
end
end
}
setmetatable(a,c)
a(1,2,3,5,6,7)
运行结果:
6. tostring元方法
重写打印的方法,和Java中类似
a = {'a','c','e'}
c = {
__tostring = function(tab)
local ret = ''
for k,v in pairs(tab) do
ret = ret..v..','
end
return ret
end
}
setmetatable(a,c)
print(a)
运行结果:
网友评论