首先我们先看下面的代码
local t = {}ttotype = { x = 100, y = 100, width = 50, height = 50}t.mt = {}function t.new(value) setmetatable(value, t.mt) return valueendt.mt.__index = ttotypet.mt.__newindex = function(table, key, value) if key == "tomyuan" then rawset(table, key, "Yes") endend-- 处理local instance = t.new({x = 33, y = 33})instance.tomyuan = "YuanBo"print(instance.tomyuan)print(instance.x)print(instance.y)print(instance.width)print(instance.height)
运行结果如下
Yes33335050
上述我们就更改了原表的行为方法
__index当我们访问表中的一个元素不存在时,则会去寻找 __index 元方法,如果存在则会返回结果,否则返回nil
local t = {}ttotype = { x = 100, y = 100, width = 50, height = 50}t.mt = {}function t.new(tb) setmetatable(tb, t.mt) return tbend--t.mt.__index = function(tb, key) if key == "TomYuan" then return "YuanBo" else return "Other" endend--local instance = t.new({ x = 100, y = 100})print(instance.TomYuan)print(instance.x)print(instance.width)
运行结果如下
YuanBo100Other__newindex
当给你的表中不存在的key进行赋值时,lua解释器则会寻找__newindex 元方法,发现存在该方法,则执行该方法进行赋值,通过rawset来进行赋值操作
local t = {}ttotype = { x = 100, y = 100, width = 50, height = 50}t.mt = {}function t.new(tb) setmetatable(tb, t.mt) return tbendt.mt.__newindex = function(tb, key, value) if key == "TomYuan" then rawset(tb, key, "Yuan Bo") endend--local instance = t.new({ x = 100, y = 100})instance.TomYuan = "Who"print(instance.TomYuan)
输出Yuan Bo
rawget和rawsetrawget是为了绕过__index而出现的,还是上面的代码
local t = {}ttotype = { x = 100, y = 100, width = 50, height = 50}t.mt = {}function t.new(tb) setmetatable(tb, t.mt) return tbendt.mt.__newindex = function(tb, key, value) if key == "TomYuan" then rawset(tb, key, "Yuan Bo") endend--local instance = t.new({ x = 100, y = 100})instance.TomYuan = "Who"print(rawget(instance ,instance.TomYuan))
输出的nil针对rawset,如果我们上面代码这么写
local t = {}ttotype = { x = 100, y = 100, width = 50, height = 50}t.mt = {}function t.new(tb) setmetatable(tb, t.mt) return tbendt.mt.__newindex = function(tb, key, value) if key == "TomYuan" then tb.key = "Yuan Bo" endend--local instance = t.new({ x = 100, y = 100})instance.TomYuan = "Who"print(instance.TomYuan)
此时输出了nil,如果__newindex里面这样的呢?
t.mt.__newindex = function(tb, key, value) tb.key = "Yuan Bo"end
则会报如下错误
stack traceback: /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' ... /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:15: in function '__newindex' /usercode/file.lua:23: in main chunk
__index 和 __newindex的区别,__index是直接取表的值,没有对应的key,则根据__index返回,__newindex主要用于表不存在的key的赋值操作。