元表
元表就是允许我们改变table的行为,你所改变的这个行为又关联了一个方法,这个方法我们称作元方法(系统提供)。
t = {}
print(getmetatable(t)) -- nil 因为没有设置其元表
m_t = {
__tostring = function (t) --设置元方法
return "aa"
end
}
t1 = setmetatable(t,m_t)
print(t) -- aa
if(t == t1)
then
print("同一张表") --输出,所以证明其实t和t1就是同一张表
end
第二种写法
t = setmetatable({},{
__tostring = function (t)
return 111
end
})
print(t)
在lua中创建新的表或者是其他类型的时候,会为该类型提供元表,但是有一个特例就是字符串
t = 10
print(getmetatable(t)) -- nil
str = "hello"
print(getmetatable(str))--string自带元表
常用创建元表的方式
setmetatable的两个参数,第一个参数为改变行为的那张表,第二个参数是元表具体的改变行为
T = setmetatable({},{})
__add(t1,t2) -- 相加行为
__sub(t1,t2) -- 相减行为
__mul -- 相乘行为
__div -- 相除行为
__len(t1) -- 表的长度
__index -- 索引查询
__newindex -- 更新索引
__tostring -- 字符串输出
......
例子
Window = {}
Window.default = {
x = 0,
y = 0,
width = 100,
height = 100,
color = {
r = 255.0,
g = 255.0,
b = 255.0
}
}
--创建一个元表
Window.mt = {}
--构造函数
function Window.new(obj)
setmetatable(obj,Window.mt)
return obj
end
--__index元方法:查询索引
Window.mt.__index = function (tb,key)
print("该方法被调用")
return Window.default[key]
end
-- Window.mt.__index = Window.default -- 指定表,如果表中没有该字段,则去这个表中的元表中找,找到__index元方法,这个方法也可以对
--应一张表,只是这样的话不能再做拦截的操作了
local win = Window.new({x = 10,y = 20})
print(win.x) --10
print(win.y) --20
print(win.width) -- 该方法被调用 100
print(win.height) -- 该方法被调用 100
print(win.x) 由于win变量本身就拥有了x字段,所以直接打印
print(win.width) 由于win变量没有该字段,那么就去查找是否拥有元表,如果有,就去元表中查询
先看元表中是否有__index元方法对应的方法或者表,
由于存在__index 所以返回default表中width字段
在实际开发中__index元方法不一定就对应的是函数,也有可能是表
最后总结一下 Lua 查找一个元素时候的规则
1.在表中查询,如果找到返回该元素,找不到继续
2.判断该表是否具备元表,如果有继续,如果没有返回nil
3.判断元表是否具备某种行为,有继续,没有nil