2012-06-05 41 views

回答

12

的Lua(其是電暈是基於語言)使用用於不同目的的元表。

的手冊中的相關條目是Section 2.8。 可以找到一個很好的教程herehere

甲元表就像任何其它表,但被設置爲元表上的另一表(我將進一步上調用基表,使表2之間的差)。

一元表可以包含任何東西,但特殊鍵(開始以雙下劃線)是有趣的。在此表中設置爲該鍵的值將在特殊場合調用。哪個場合取決於哪​​個鍵。最有趣的是:

  • __index:只要基表中的鍵被查找,但不存在就會使用。這可以包含表格,其中將查找關鍵字,也可以包含將傳遞原始表格和關鍵字的函數。這可以用於在表格上實現方法(OOP風格),用於重定向,通過案例設置,設置默認值等等。
  • __newindex:將在表中分配新密鑰時使用(之前爲零)。如果它是一個表格,那麼該表格中將分配該鍵。如果它是一個函數,該函數將傳遞原始表,鍵和值。這可以用於控制對錶格的訪問,數據的預處理,分配的重定向。
  • __call:使您可以設置一個函數,如果您使用例如。 table()
  • __add,__sub,__mul,__div,__mod用於實現二進制操作,
  • __unm被用來實現一元運算,
  • __concat用於實現級聯(在..運營商)
  • __len用於實現長度操作
  • __eq,__lt,__le用於執行比較

一件小事在這些方法中使用__index &合作:當知道(#),你應該使用rawget和rawset,以防止每次再次調用metamethod,導致循環。 作爲一個小例子:

t={1,2,3} -- basetable 
mt={} -- metatable 
mt.__index=function(t,k) 
    print("__index event from "..tostring(t).." key "..k) 
    return "currently unavailable" 
end 
mt.__newindex=function(t,k,v) 
    print("__newindex event from "..tostring(t).." key: "..k.." value: "..v) 
    if type(k)=="string" then 
     rawset(t,k,v:reverse()) 
    else 
     rawset(t,k,v) 
    end 
end 
mt.__call=function(t,...) 
    print("call to table "..tostring(t).." with arguments: ".. table.concat({...},',')) 
    print("All elements of the table:") 
    for k,v in pairs(t) do print(k,v) end 
end 
setmetatable(t,mt) 

t[4]="foo" -- this will run the __newindex method 
print(t[5]) -- this will run the __index method 
t("foo","bar") 
-- Multiple fall through example: 
t={} 
mt={} 
mt2={} 
setmetatable(t,mt) -- metatable on base table 
setmetatable(mt,mt2) -- second layer of metatable 
mt.__index=function(t,k) print('key '..k..' not found in '..namelookup[t]) return getmetatable(t)[k] end -- tries looking nonexistant indexes up in mt. 
mt2.__index=mt.__index -- function was written portably, reuse it. 

t[1]='A' 
mt[2]='B' 
mt2[3]='C' 
namelookup={[t]="t",[mt]="mt",[mt2]="mt2"} 
print(t[1],t[2],t[3],t[4]) 

現在,這些不過是無聊的例子,你可以做更復雜的東西。看看這些例子,看看Programming in Lua中的相關章節和實驗。並儘量不要感到困惑;)

13

表在Lua是你可以用它來創建動態的,結構化數據的主要數據類型。其他語言有數組,列表,字典(鍵值存儲),在Lua中只有表格。你可以用一個基本的表格做的唯一操作的索引和使用tab[key]語法存儲值,即:

local tab = {} 
tab['key1'] = 'Hello' -- storing a value using a string key 
tab.key2 = 'World' -- this is syntax sugar, equivalent to previous 
print(tab.key1, tab['key2']) -- indexing, the syntax is interchangable 

你不能做任何其他與基本表,例如添加他們:

local v1={x=0,y=0} 
local v2={x=1,y=1} 
print(v1+v2) 
--> stdin:1: attempt to perform arithmetic on local 'v1' (a table value) 

一個元表允許你修改表的行爲,指定添加表時,應該做什麼,乘,級聯(..)等。元表只是一個表,其中包含具有特殊功能鍵,也被稱爲metamethods。您可以使用setmetatable()將元數據分配給表。例如:

local Vector = {} -- this will be the metatable for vectors 

function Vector.__add(v1, v2) -- what to do when vectors are added 
    -- create a new table and assign it a Vector metatable 
    return setmetatable({x=v1.x+v2.x, y=v1.y+v2.y}, Vector) 
end 
function Vector.__tostring(v) -- how a vector should be displayed 
    -- this is used by tostring() and print() 
    return '{x=' .. v.x .. ',y=' .. v.y .. '}' 
end 

local v1 = setmetatable({x=1, y=2}, Vector) 
local v2 = setmetatable({x=3, y=4}, Vector) 

-- vectors are added and the resulting vector is printed 
print(v1 + v2) --> {x=4,y=6} 

如果你想更好地瞭解元表,你一定要read the Programming in Lua chapter on metatables

+4

好具體的例子! –