表格函数二 |
|
为了效率,它限制了私有键不能具有值 nil
(将私有键设置为 nil 将发布该键)。现在我们有了 false
,我认为这并不那么重要。(好吧,也许 false
不是一个坏主意 :) )
有趣的是,公共状态表中没有保留键,客户端程序可以自由使用恰好是私有的键。在这种情况下,客户端程序和表格函数看到不同的表格。
我没有在这里添加任何继承,但这并不困难。私有表需要在尝试公共表之前检查它继承的对象的私有表,而公共表只有一个 __index
元方法,其值为相同对象的公共表。这更像是对象原型而不是类继承,但它通常是一种有用的编程风格。
do -- the private table just forwards to the public table. local private_meta = { __index = function(t, k) return t.__public[k] end, __newindex = function(t, k, v) t.__public[k] = v end, __call = function(t, ...) return t.__function(t, unpack(arg)) end } function Tablefunc(fn, private) -- this is what the caller will see local public = {} -- remember what we do and where we do it private.__function = fn private.__public = public -- normally I'm not in favour of privatisation, but -- sometimes you have to do it. -- Call this as follows: -- self:privatise {private_key = initial_value, -- other_private_key = initial_value} function private.privatise(self, vars) for k, v in vars do rawset(self, k, v) end end -- set up the deferral metamethods setmetatable(private, private_meta) -- create a new metatable with a __call metamethod which -- accesses the private table through a closure. return setmetatable(public, { __call = function(t, ...) return private.__function(private, unpack(arg)) end }) end end
让我们来试用一下。
function test(self, x) if x then self:privatise({public = "public hidden"}) end print("hidden:", self.hidden) print("public:", self.public) end
$lua Lua 5.0 (beta) Copyright (C) 1994-2002 Tecgraf, PUC-Rio > a = Tablefunc(test, {hidden = "hidden"}) > a() hidden: hidden public: nil > a.public = "public" > a() hidden: hidden public: public > a.hidden = "change hidden" > a() hidden: hidden public: public > = a.hidden change hidden > -- here we tell the function to make "public" private > a(1) hidden: hidden public: public hidden > = a.public public > a.public = "change public" > a() hidden: hidden public: public hidden > = a.public change public
--RiciLake