表格函数二

lua-users home
wiki

这是一个 表格函数 的版本,其中包含私有和公共持久状态。

为了效率,它限制了私有键不能具有值 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


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2007 年 5 月 28 日下午 5:16 GMT (差异)