Corona中表格和元表之间有什么区别? metatables有哪些类型?我如何以及在何处使用它们?使用表和元表的主要目的是什么?
答案 0 :(得分:15)
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)
metatable 允许您修改表的行为,指定在添加,乘法,连接(..
)等表时应该做什么。一个metatable只是一个table,包含具有特殊键的函数,也称为 metamethods 。您可以使用setmetatable()
将metatable分配给表。例如:
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。
答案 1 :(得分:13)
Lua(Corona所依据的语言)将metatable用于不同目的。
手册中的相关条目为Section 2.8。 可以找到一个很好的教程here或here。
metatable只是一个像其他任何表一样的表,但在另一个表上设置为metatable(我将进一步称之为基表,以区分两个表)。
metatable可以包含任何内容,但特殊键(以双下划线开头)是有趣的。在此表中设置为此键的值将在特殊情况下调用。哪个场合取决于哪个键。最有趣的是:
__index
:只要查找基表中的键但不存在,就会使用它。这可以包含表,其中将查找键,或者一个函数,它将传递原始表和键。这可以用于实现表上的方法(OOP样式),重定向,通过案例,设置默认值等等。__newindex
:只要在表中分配新密钥(之前为零),就会使用它。如果是表,则将在该表中分配密钥。如果它是一个函数,那么该函数将传递原始表,键和值。这可用于控制对表的访问,预处理数据,分配的重定向。__call
:如果您使用eg,则可以设置要调用的函数。 table()
。__add,__sub,__mul,__div,__mod
用于实现二进制操作,__unm
用于实施一元操作,__concat
用于实现连接(..运算符)__len
用于实现长度运算符(#)__eq,__lt,__le
用于实施比较使用__index&时要知道的一件小事co。:在这些方法中,你应该使用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中的相关章节,然后进行实验。并尽量不要混淆;)