metatable
什么是元表
元表像是一个“操作指南”,里面包含了一系列操作的解决方案,例如__index方法就是定义了这个表在索引失败的情况下该怎么办。
__index元方法
很多人对此都有误解,这个误解是:如果A的元表是B,那么如果访问了一个A中不存在的成员,就会访问查找B中有没有这个成员。而这个理解是完全错误的,实际上,即使将A的元表设置为B,而且B中也确实有这个成员,返回结果仍然会是nil,原因就是B的__index元方法没有赋值。别忘了我们之前说过的:“元表是一个操作指南”,定义了元表,只是有了操作指南,但不应该在操作指南里面去查找元素。
示例
father = {
house = 1
}
son = {
car = 1
}
setmetable(son,father)
print(son.house) --nil
修改代码如下:
father = {
house = 1
}
father.__index = father --把father的__index方法指向自己
son = {
car = 1
}
setmetable(son,father)
print(son.house) --1
在上述例子中,访问son.house时,son中没有house这个成员,但Lua接着发现son有元表father,注意:此时,Lua并不是直接在father中找名为house的成员,而是调用father的__index方法,如果__index方法为nil,则返回nil,如果是一个表(上例中father的__index方法等于自己,就是这种情况),那么就到__index方法所指的这个表中查找名为house的成员,于是,最终找到了house成员。
注:__index方法除了可以是一个表,还可以是一个函数,如果是一个函数,__index方法被调用时将返回该函数的返回值。
总结一下Lua查找一个表元素时的规则,其实就是如下3个步骤:
1、在表中查找,如果找到,返回该元素,找不到则继续
2.判断该表是否有元表(操作指南),如果没有元表,返回nil,有元表则继续
3.判断元表(操作指南)中有没有关于索引失败的指南(即__index方法),如果没有(即__index方法为nil),则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值
参考网址:Lua查找表元素过程(元表、__index方法是如何工作的)
lua类实现继承
定义类
--声明,这里声明了类名还有属性,并且给出了属性的初始值。
Class = {x = 0 , y = 0}
--这句是重定义元表的索引,就是说有了这句,这个才是一个类。具体的解释,请参照上面
Class.__index = Class
--构造体
function Class:new(x,y)
local self = {} --初始化self,如果没有这句,那么类所建立的对象改变,其他对象都会改变
setmetatable(self, Class) --将self的元表设定为Class
self.x = x --属性值初始化
self.y = y
return self --返回自身
end
--这里定义类的其他方法
function Class:test()
print(self.x,self.y)
end
继承
--声明了新的属性Z
Main = {z = 0}
--设置类型是Class
setmetatable(Main, Class)
--还是和类定义一样,表索引设定为自身
Main.__index = Main
--这里是构造体
function Main:new(x,y,z)
local self = {} --初始化对象自身
self = Class:new(x,y) --将对象自身设定为父类,这个语句相当于其他语言的super
setmetatable(self, Main) --将对象自身元表设定为Main类
self.z= z --新的属性初始化,如果没有将会按照声明=0
return self
end
--定义一个新的方法
function Main:go()
self.x = self.x + 10
end
--重定义父类的方法
function Main:test()
print(self.x,self.y,self.z)
end
参考网址 Lua的类实现继承