小细节 :一般运行lua程序是 lua ./文件名
但可以在这个lua文件开头加上这句话,则可以直接 ./文件名 就可以执行对应文件
#!/usr/local/bin/lua
假设文件名是hello.lua , 则可以直接 ./hello.lua 执行这个文件
这个路径有可能跟我不一样,要看lua在哪里
– pairs 和 ipairs的区别
– ipairs遍历table时,键值从1递增,当键值中断(如[1]过了就是[3])或遇到nil时退出
– pairs 会遍历表中所有键值对,且元素是根据哈希算法来排序的,所以打印出来的顺序是乱的
简单说一下什么是元表和元方法
test = {}
test.hello = function()
print("hha")
end
元表可以绑定在一个普通的表或者一个userdata上, 比如现在有一个普通表test, 当我们正常调用test.hello的时候,可以正常的调用这个函数,但如果我们调用test.world, 我们可以发现,test表中并没有world的对应函数,于是就会去与test表绑定的元表中寻找world函数。
我上边说的这种情况(找不到world函数),会去test的元表中寻找__index 字段,当然只是上边这种情况会去寻找__index字段对应的处理方式, 还有其他处理方式,后边会一一介绍,__tostring, __call方法等。
这里我们假设Vector 是一个元表
Vector = {}
Vector.__index = Vector
– 这步必须要,因为Vector是一个元表,当这个元表对应的普通表找不到对应的函数的时候
– 就会去这个元表(Vector)的__index中查找,这样设置后,__index中就包含元表的所有函数,即整个元表
– 需要理解一点 __index只是一个元方法,当出现在普通表中找不到函数的情况
– 就会去找这个普通表对应的元表的__index方法,来进一步寻找,就和__tostring, __call 一样
– 元方法只是普通表遇到特定情况时的解决方案,所以这种情况下需要设置 元表.__index = 元表
重点:只是__index 字段是这样设置,__tostring,__call就不是这样设置的,所以需要清楚明白的一点就是,Vector.__index = Vector这样只是为了设置__index元方法这一种元方法,还有很多其他的元方法。
学习建议:跟着把下边的代码都敲一遍,并且每一个案例都成功运行,就能学懂lua中的元表和元方法。
所谓的元表和普通表一样,都是table结果,是否作为元表,取决于你自己的操作
lua中的结构中只有table和userdata可以独立的设置元表
__index元方法
这是metatable元表最常用的键了。
当你通过键来访问table的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的 __index 键。如果 __index 包含一个表格,Lua会在表格中查找相应的键。
t = {} --作为普通表
mt = {} --作为元表
setmetatable(t,mt);-- 会将第二个表设置为第一个参数的表的原表
getmetatable(t);
t = setmetatable({[2] = 3}, {
__index = function(t,key)
if key == "foo" then
return 0
else
return table[key]
end
end
});
other = {foo = 3}
-- t = setmetatable({}, {__index = other})
print(t.foo) -- 0
print(t.bar) -- nil
print(t[2]) --3
__newindex 元方法
类似 __index , __newindex 的值为函数或table,用于按键赋值的情况。
当对一个table中不存在的索引赋值时,解释器就会查找__newindex元方法
other = {}
-- setmetatable 会将第二个表设置为第一个参数的表的原表
-- 并且会将第一个参数的表返回
t = setmetatable({}, {__newindex = other})
t.foo = 3
t = setmetatable({}, {
__newindex = function(t, key, value)
if type(value) == "number" then
rawset(t, key, value * value)
else
rawset(t, key, value)
end
end
})
t.foo = "foo"
t.bar = 4
t.la = 10
print(t.foo)
print(t.bar)
print(t.la)
__mul 元方法 (乘法)
t = setmetatable({1,2,3}, {
__mul = function(t, other)
new = {}
for i = 1, other do
for _, v in ipairs(t) do
table.insert(new, v)
end
end
return new
end
})
t = t * 2 -- 将上边的1,2,3 变成了1,2,3,1,2,3
for v,k in pairs(t) do
print(v,k) --这种方式会把key和value一起打印出来
end
__call 的原方法
使得你可以像调用函数一样调用table:
也就是当table名字作为函数名字的时候会被调用
下边可以观察到,本来t是一个table,却当作函数来使用
t = setmetatable({}, {
__call = function(t, a, b, c, whatever)
return (a +b +c) * whatever
end
})
print(t(1,2,3,4))
__tostring的元方法
– 它可以将一个table转换成字符串,常和print配合使用
– 如果不使用__tostring元方法,默认的print(表名) 会打印处一串地址
t = setmetatable({1, 2 ,3}, {
__tostring = function(t)
sum = 0
for _, v in pairs(t) do
sum = sum + v
end
return "Sum:"..sum
end
})
print(t)