提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
面试腾讯的时候有问到lua的内容,其中主要集中在热更新和元表、元方法上面,因为踩过了坑所以打算写一篇来记录一下
一、元表
本篇介绍的是元表、元表table是lua中唯一的数据结构,table在我使用来说可以当成很多东西,能够实现类、继承、又能像结构体,table里面能够添加任意元素
t= {
a = 10,
b = 100,
c = "abc"
}
这样table就有点像结构体
二、元方法
元方法的存在是为了让我们的元表之间能够相互交互,元方法能够让被赋予的元表之间能够执行特定操作
t = {
a = 10,
b = 100,
c = "abc"
}
mt = {
__add = function(a,b)
return a.a + b
end,
}
setmetatable(t, mt)
print(t + 2)
其中mt为元方法,setmetatable的方法会将mt中的方法赋予给t元表,这样的话t方法就能够进行操作,这里是lua文档,详细的元方法内容可以看lua文档,在我看来有点像回调,元方法其实是元表,但是在里面写的是函数方法,有需要的元表能够订阅元方法,要注意一点,只有订阅了相同元方法的元表之间才能够相互交互,不然会返回nill或者报错,元表里面还能够在表里面写自己的函数
t = {
a = 10,
b = 4,
c = "abc",
__my = function(a,b)
return a + b
end
}
print(t.__my(t.a,t.b))
个人见解
lua在我的认知里面是一种调用者的角色,因为lua作为脚本语言最大的特色是不需要进行编译的过程,因此每次修改都不需要重新执行一次,这个特性在已经上架了的游戏来说十分重要,线上的项目每次修改都需要重新经过审核,调用lua之后不需要编译的特性省去了很多麻烦,需要修改bug上传资源都不需要重新经过审核,而在实际开发中可以让lua调用C#等文件,可以理解为C#脚本编写了对应的功能,再用lua去组合调用,结合不需要编译能省去很多调试的时间.
三、面向对象
上面我们讲了元表和元方法,我们将元表视为对象,而我们在元方法中编写函数,将元方法赋予对象即可完成面向对象,先上例子
bag = {}
bagmt = {--元方法
put = function(t,item)
table.insert(t.items,item)
end,
take = function(t)
return table.remove(t.items,item)
end,
list = function(t)
return table.concat(t.items,",")
end,
clear = function(t)
t.items = {}
end,
}
bagmt["__index"] = bagmt--这里是将index元方法赋予自己,作用是调用不存在的函数时会在bagmt里找
function bag.new()--构造函数
local t = {
items = {}
}
setmetatable(t,bagmt)
return t
end
local b = bag.new()
b:put("apple")
b:put(666)
b:put(1)
print(b:list())
这里可以看出编写了构造函数之后,在构造函数里面对构造的元表赋予元方法之后该表就成了对象,就能完成面向对象操作,笔者之前是学c++的,在这里就会发现其实在构造函数这一块比较相同,就是构造函数如果是最初的父类那么还是要在里面编写函数,但lua的话是在外面写完之后再赋予,结果上来说是相同的。
如果需要对象之间相互交互就可能需要源自同一构造函数,再编写对应的元方法。
总结
在我看来元表是lua唯一数据结构,但这个数据结构能够作为类、结构体,在元方法调用之后还能够赋予对应的操作函数,从而达到将元表作为对象操作,达到面向对象的操作。