English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作。
因此 Lua 提供了元表(Metatable),允许我们改变table的行为,每个行为关联了对应的元方法。
例如,使用元表我们可以定义Lua如何计算两个table的相加操作a+b。
当Lua试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫"__add"的字段,若找到,则调用对应的值。"__add"等即时字段,其对应的值(往往是一个函数或是table)就是"元方法"。
有两个很重要的函数来处理元表:
setmetatable(table,metatable): 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。
getmetatable(table): 返回对象的元表(metatable)。
以下示例演示了如何对指定的表设置元表:
mytable = {} -- 普通表 mymetatable = {} -- 元表 setmetatable(mytable,mymetatable) -- 把 mymetatable 设为 mytable 的元表
Il codice sopra può anche essere scritto in una riga:}
mytable = setmetatable({},{})
Di seguito è riportato l'esempio di tabella meta restituita:
getmetatable(mytable) -- Questo restituirà mymetatable
Questa è la chiave più utilizzata nella tabella meta.
Quando accedi a una tabella tramite una chiave, se la chiave non ha un valore, Lua cerca la tabella meta (supponiamo che esista una tabella meta) con la chiave __index.
Possiamo usare il comando lua per entrare in modalità interattiva e vedere:
$ lua Lua 5.3.0 Copyright (C) 1994-2015 Lua.org, PUC-Rio > other = { foo = 3 } > t = setmetatable({}, { __index = other }) > t.foo 3 > t.bar nil
Se __index contiene una funzione, Lua chiama quella funzione, passando la tabella e la chiave come parametri alla funzione.
Il metodo meta __index verifica l'esistenza dell'elemento nella tabella, se non esiste, il risultato è nil; se esiste, il risultato è restituito da __index.
mytable = setmetatable({key1 = "value1"}, { __index = function(mytable, key) if key == "key2" then return "metatablevalue" else return nil end end ) print(mytable.key1,mytable.key2)
Esempio di risultato di output:
value1 metatablevalue
Esempio di解析:
Assegna il valore a mytable: {key1 = "value1"}
mytable ha impostato la tabella meta, il metodo meta è __index.
Cerca key1 nella tabella mytable, se la trovi, restituisce quell'elemento, se non la trovi, continua.
Cerca key2 nella tabella mytable, se la trovi, restituisce metatablevalue, altrimenti continua.
Verifica se la tabella meta ha il metodo __index, se __index è una funzione, chiama quella funzione.
Controlla nel metodo meta se è stato passato il parametro chiave "key2" (mytable.key2 è stato impostato), se è stato passato il parametro "key2", restituisce "metatablevalue", altrimenti restituisce il valore della chiave corrispondente a mytable.
Possiamo scrivere semplicemente il codice sopra: }}
mytable = setmetatable({key1 = "value1"}, {__index = {key2 = "metatablevalue"}}) print(mytable.key1,mytable.key2)
Conclusione
Le regole di ricerca di un elemento nella tabella di Lua sono in realtà tre passaggi come segue:
1. Cerca nella tabella, se trova un elemento, restituisce quell'elemento, se non trova nulla, continua
2. Verifica se la tabella ha una tabella meta, se non ce n'è, restituisce nil, se c'è, continua.
3. Verifica se il metodo __index della tabella meta esiste, se __index è nil, restituisce nil; se __index è una tabella, ripeti i punti 1, 2, 3; se __index è una funzione, restituisce il valore di ritorno della funzione.
Questa parte del contenuto è stata fornita dall'autore寰子: https://blog.csdn.net/xocoder/article/details/9028347
Il metodo meta __newindex viene utilizzato per aggiornare la tabella, mentre __index viene utilizzato per accedere alla tabella.
Quando si assegna un valore a un indice mancante nella tabella, l'interprete cerca il metodo meta __newindex: se esiste, chiama questa funzione senza effettuare l'operazione di assegnazione.
L'esempio seguente dimostra l'applicazione del metodo meta __newindex:
mymetatable = {} mytable = setmetatable({key1 = "value1"}, {__newindex = mymetatable}) print(mytable.key1) mytable.newkey = "valore nuovo2" print(mytable.newkey, mymetatable.newkey) mytable.key1 = "valore nuovo1" print(mytable.key1, mymetatable.key1)
I risultati di esecuzione degli esempi sopra sono:
value1 nil valore nuovo2 valore nuovo1 nil
Nell'esempio riportato, la tabella ha impostato il metodo meta __newindex, quando si assegna un nuovo chiave di indice (newkey) (mytable.newkey = "valore nuovo2"), viene chiamato il metodo meta, senza effettuare l'assegnazione.
Ecco un esempio che utilizza la funzione rawset per aggiornare la tabella:
mytable = setmetatable({key1 = "value1"}, { __newindex = function(mytable, key, value) rawset(mytable, key, "\""..value.."\"") end ) mytable.key1 = "new value" mytable.key2 = 4 print(mytable.key1,mytable.key2)
I risultati di esecuzione degli esempi sopra sono:
Nuovo valore "4"
Ecco un esempio che dimostra l'operazione di somma tra due tabelle:
-- La funzione massima della tabella, table.maxn, non è più disponibile nelle versioni superiori al Lua 5.2 -- Funzione massima di calcolo personalizzata per il numero di elementi della tabella, table_maxn function table_maxn(t) local mn = 0 for k, v in pairs(t) do if mn < k then mn = k end end return mn end -- Operazione di somma tra due tabelle mytable = setmetatable({ 1, 2, 3 }, { __add = function(mytable, newtable) for i = 1, table_maxn(newtable) do table.insert(mytable, table_maxn(mytable)+1,newtable[i]) end return mytable end ) secondtable = {4,5,6} mytable = mytable + secondtable for k,v in ipairs(mytable) do print(k,v) end
I risultati di esecuzione degli esempi sopra sono:
1 1 2 2 3 3 4 4 5 5 6 6
__add chiave inclusa nella tabella meta e sommata. Elenco delle operazioni corrispondenti nella tabella: (Attenzione:__è due underscore)
Modo | Descrizione |
---|---|
__add | Operatore corrispondente '+'. |
__sub | Operatore corrispondente '-'. |
__mul | Operatore corrispondente '*'. |
__div | Operatore corrispondente '/'. |
__mod | Operatore corrispondente '%'. |
__unm | Operatore corrispondente '-'. |
__concat | Operatore corrispondente '..'. |
__eq | Operatore corrispondente '=='. |
__lt | Operatore corrispondente '<'. |
__le | Operatore corrispondente '<='. |
__call metodo meta chiamato quando Lua chiama un valore. Ecco un esempio che dimostra come calcolare la somma degli elementi della tabella:
-- La funzione massima della tabella, table.maxn, non è più disponibile nelle versioni superiori al Lua 5.2 -- Funzione massima di calcolo personalizzata per il numero di elementi della tabella, table_maxn function table_maxn(t) local mn = 0 for k, v in pairs(t) do if mn < k then mn = k end end return mn end -- Definire il metodo meta __call mytable = setmetatable({10}, { __call = function(mytable, newtable) sum = 0 for i = 1, table_maxn(mytable) do sum = sum + mytable[i] end for i = 1, table_maxn(newtable) do sum = sum + newtable[i] end return sum end ) newtable = {10, 20, 30} print(mytable(newtable))
I risultati di esecuzione degli esempi sopra sono:
70
Il metodo meta __tostring viene utilizzato per modificare il comportamento di output della tabella. Nei seguenti esempi, abbiamo personalizzato il contenuto di output della tabella:
mytable = setmetatable({10, 20, 30}, { __tostring = function(mytable) sum = 0 for k, v in pairs(mytable) do sum = sum + v end return "La somma di tutti gli elementi della tabella è " .. sum end ) print(mytable)
I risultati di esecuzione degli esempi sopra sono:
La somma di tutti gli elementi della tabella è 60
Da questo articolo possiamo sapere che il metatable può semplificare notevolmente le funzionalità del nostro codice, quindi conoscere il metatable di Lua ci permette di scrivere codice Lua più semplice ed eccellente.