接上篇:
2、__newindex Metamethod
__index metamethod是对table的访问,__newindex metamethod则是用来对表的更新。当给表的一个缺少的域赋值时,lua解释器会查找__newindex metamethod,如果存在,则调用这个函数而不进行赋值操作。
详细的,在lua面向对象编程中介绍。
3、下边介绍几种利用metatable 实现的功能和表的操作。
有默认值的表,当我们访问一个表不存在的域的时候,默认值是nil,我们可以通过metatable改变它的默认值。
第一种方式:这样改变多个表的默认值代价太大。
-------------代码段-----------------
local Set = {}
function Set.SetDefaultValue(tab, value)
setmetatable(tab, {__index = function() return value end})
end
-- 测试
local test_table = {}
Set.SetDefaultValue(test_table, "*")
print(test_table.x) -->*
-------------代码段-----------------
第二种方式:把默认值放在自己的表中的一个域。
-------------代码段-----------------
local Set = {}
local meta_table = {__index = function(tab) return tab.___default___value end}
function Set.SetDefaultValue(tab, value)
tab.___default___value = value
setmetatable(tab, meta_table)
end
-- 测试
local test_table = {}
Set.SetDefaultValue(test_table, "*")
print(test_table.x) -->* 这种方式用ipairs可以遍历到
-------------代码段-----------------
第三种方式:新建一个表作为键值,可以保证这个键值的唯一性。
-------------代码段-----------------
local Set={}
function Set.SetDefaultValue(tab, value)
local key={}
local meta_table = {__index =
function(tab)
return tab[key]
end}
tab[key] = value
setmetatable(tab, meta_table)
end
-- 测试
local test_table = {}
Set.SetDefaultValue(test_table, "*")
print(test_table.x) -->* 这种方式用ipairs可以遍历到
-------------代码段-----------------
监控对一个表的操作,使用代理table。
-------------代码段-----------------
local index = {} --为了保证域的唯一性
local mt = {
__index = function(t,k)
print("access table element: " .. tostring(k))
return t[index][k]
end,
__newindex = function(t,k,v)
print("change table valu: " ..
tostring(k) .. " = " ..tostring(v))
t[index][k] = v
end
}
-- 设置代理表
function track(t)
local proxy = {}
proxy[index] = t
setmetatable(proxy,mt)
return proxy
end
-- 测试
local mytable = {}
mytable = track(mytable)
mytable["sex"] = "man"
print(mytable["sex"])
-------------代码段-----------------
实现只读表:
-------------代码段-----------------
--[[
这里注意函数error(param1,param2)
param1=>错误信息
param2=>可选参数,默认为1打印会显示调用error的位置(文件+行号),
2 显示调用的函数
0 不显示错误位置信息
]]--
function create_only_reader_table(tab)
local proxy = {}
local mt = {
__index = tab,
__newindex = function(t,k,v)
error("not change table value", 2)
end
}
setmetatable(proxy, mt)
return proxy
end
-- 测试
local info = {["name"] = "xiaoming", ["sex"] = "man", ["prof"] = "teacher"}
local tab = create_only_reader_table(info)
tab["name"] = "ww"
-------------代码段-----------------
Metatable总结:
1、算术域、关系域、库的域、表的域、(域这里指__add、__le、__index等),通过设置这些域的值(值可以是函数、表、字符串、变量等),来改变lua原有的行为。
2、通过设置多个相同表的共同原表,可以模拟面向对象中的继承。
3、通过设置自己的原表,描述自己私有行为。
-------------2018/10/19-----------
|
请发表评论