資料表函數 2

lua-users home
wiki

以下是 TableFuncs 版本,其中同時有私人和公共的持續狀態。

為了效率,這有一定限制,即私人金鑰無法為值 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 編輯 (差異)