LUA教程表相关的Metamethods 有默认值的表 -56

function setDefault (t, d)
    local mt = {__index = function () return d end}
    setmetatable(t, mt)
end 
 
tab = {x=10, y=20}
print(tab.x, tab.z)      --> 10   nil
setDefault(tab, 0)
print(tab.x, tab.z)      --> 10   0

现在,不管什么时候我们访问表的缺少的域,他的__index metamethod被调用并返回0。setDefault函数为每一个需要默认值的表创建了一个新的metatable。在有很多的表需要默认值的情况下,这可能使得花费的代价变大。然而metatable有一个默认值d和它本身关联,所以函数不能为所有表使用单一的一个metatable。为了避免带有不同默认值的所有的表使用单一的metatable,我们将每个表的默认值,使用一个唯一的域存储在表本身里面。如果我们不担心命名的混乱,我可使用像"___"作为我们的唯一的域:

local mt = {__index = function (t) return t.___ end}
function setDefault (t, d)
    t.___ = d
    setmetatable(t, mt)
end

如果我们担心命名混乱,也很容易保证这个特殊的键值唯一性。我们要做的只是创建一个新表用作键值:

local key = {}    -- unique key
local mt = {__index = function (t) return t[key] end}
function setDefault (t, d)
    t[key] = d
    setmetatable(t, mt)
end

另外一种解决表和默认值关联的方法是使用一个分开的表来处理,在这个特殊的表中索引是表,对应的值为默认值。然而这种方法的正确实现我们需要一种特殊的表:weak table,到目前为止我们还没有介绍这部分内容,将在第17章讨论。

为了带有不同默认值的表可以重用相同的原表,还有一种解决方法是使用memoize metatables,然而这种方法也需要weak tables,所以我们再次不得不等到第17章。


发布日期:

所属分类: 编程 标签:


没有相关文章!