元表
lua的元表是表的一个扩展,可以简化表的一些操作。setmetatable
关键字是设置元表的核心操作。
__index
相当于建立索引,为查找表元素提供了方便。
Lua 查找一个表元素时的规则,其实就是如下 3 个步骤: (参考自https://blog.csdn.net/xocoder/article/details/9028347)
- 在表中查找,如果找到,返回该元素,找不到则继续
- 判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。
- 判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果 __index 方法是一个表,则重复 1、2、3;
- 如果 __index 方法是一个函数,则返回该函数的返回值,table和键会作为参数传递给函数。
给出代码实例:
other = {foo = 3}
t = setmetatable({}, {__index = other})
print(t.foo)
mytable = setmetatable({key1 = "key2"}, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return nil
end
end
})
print(mytable.key1)
print(mytable.key2)
函数的输出是:
3
key2
metatablevalue
可以给表添加操作符号,以__add
为例子:
function table_maxn(t)
local mn = 0
for k, v in pairs(t) do
if mn < k then
mn = k
end
end
return mn
end
mytable = setmetatable({1, 2, 3}, {
__add = function(mytable, newtable)
for i = 1, table_maxn(newtable) do
table.insert( mytable, table_maxn(mytable) + 1, newtable[i])
end
return mytable
end
})
secondtable = {4, 5, 6}
mytable = mytable + secondtable
for k, v in ipairs(mytable) do
print(k, v)
end
同样的,函数以mytable
和`操作符后面的表作为输入。还有其他的操作符号,可以查找对应的表数据。
__call
方法在lua调用一个值时进行调用,给出代码实例:
function table_maxn(tb)
local mn = 0
for k, v in pairs(tb) do
if k > mn then
mn = k
end
end
return mn
end
mytable = setmetatable({1, 2, 3}, {
__call = function(mytable, newtable)
local sum = 0
for i = 1, table_maxn(mytable) do
sum = sum + mytable[i]
end
for i = 1, table_maxn(newtable) do
sum = sum + newtable[i]
end
return sum
end
})
newtable = {4, 5, 6}
print(mytable(newtable)) -- 输出21
相当于一个元表本身就是一个函数了。
__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
模块
新建一个module1
的模块,命名为model1.lua
module1 = {}
module1.constant = "This is constant"
function module1.func1()
print("public function")
end
local function func2()
print("This is a private function")
end
function module1.func3()
func2()
end
return module1
新建main.lua
文件,内容如下:
local m = require("./module1")
print(module1.constant) -- 报名调用
m.func1() -- 变量调用
module1.func3()
如果是加载C语言的动态链接库,可以直接写成:
local path = "/usr/local/lua/lib/mylua.so"
local f = loadlib(path, "luaopen_socket")
Lua 面向对象
Lua中,一个类使用table表示的,同时还需要借助元表的技术,给出代码实例:
Rectangle = {width = 0, height = 0}
function Rectangle:new (o, width, height)
o = o or {}
setmetatable(o, self) -- 通过元表的方式,来确定新对象,也可以进行引用操作
self.__index = self
self.width = width or 0
self.height = height or 0
return o
end
function Rectangle: area ()
return self.width * self.height
end
rect = Rectangle:new(nil, 10, 20) -- 新建对象
print(rect:area()) -- 200
rect1 = Rectangle:new(rect1, 20, 30) -- 传递对象的引用,同时改变对应的值
print(rect:area()) -- 600
print(rect1:area()) -- 600
print(rect.width) -- 20