Metatable元表
lua中的每个值都可以用一个metatable
两个table类型的变量,你是无法直接用 + 操作的,如果你定义了一个指定的函数,就可以进行了
setmetatable(table,metatable):对指定table设置元表(metatable),如果元表中存在__metatable键值,setmetatable会失败
getmetatable(table):返回对象的元表
元表创建
lua在创建新的table时不会创建元表1
2local t = {1,2}
print(getmetatable(t)) -- nil
使用getmetatable来获取一个table或userdata类型变量的元表,当创建新的table变量时,使用getmetatable去获得元表,将返回nil,同理,我们也可以使用setmetatable去设置一个table或者userdata类型变量的元表
lua代码中,只能设置table元表1
2
3
4
5
6
7
8
9
10
11
12
13
14local t = {}
setmetatable(t,t1)
assert(getmetatable(t) == t1)
print(getmetatable("hello world"))
print(getmetatable(10))
=====结果=====
nil
table:0061DE68
nil
__index元方法
当我们访问一个table中不存在的字段时,得到的结果是nil,但是这种状况很容易被改变,lua是按照以下步骤决定是返回nil还是其他的值:
当访问一个table字段时,如果table有这个字段,则直接返回对应值。
当table没有这个字段,则会促使解释器去查找一个叫__index的元方法,接下来就会调用对应的元方法,返回元方法的值。
如果没有这个元方法,那么返回nil结果1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22Windows = {} -- 创建一个命名空间
-- 创建默认值表
Windows.default = {x=0,y=0,width=100,height=100,color={r=255,g=255,b=255}}
Windows.mt = {} -- 创建元表
-- 声明构造函数
function Windows.new(o)
setmetatable(o,Windows.mt)
return 0
end
-- 定义__index元方法
Windows.mt.__index = function(table,key)
return Windows.default[key]
end
local win = Windows.new({x=10,y=10})
print(win.x) -- 10
print(win.width) -- 100
print(win.color.r) -- 255
__index元方法不必一定是一个函数,他还可以是一个table
__newindex元方法
newindex元方法与index类似,newindex用于更新table中的数据,而index用于查询table中的数据
lua解释器先判断这个table是否有元表
如果有元表,就查找元表中是否有__newindex元方法,如果没有元表,就直接添加这个索引,然后对应的赋值
如果有这个__newindex元方法,lua解释器就执行它,而不是执行赋值
如果这个__newindex对应的不是一个函数,而是一个table,lua解释器就在这个table中执行赋值么不是对原来的table1
2
3
4
5
6
7
8
9local tb1 = {}
local tb2 = {}
tb1.__newindex = tb2
tb2.__newindex = tb1
setmetatable(tb1,tb2)
setmetatable(tb2,tb1)
tb1.x = 10