Lua - Métatables
Une métatable est une table qui aide à modifier le comportement d'une table à laquelle elle est attachée à l'aide d'un jeu de clés et des méta-méthodes associées. Ces méta-méthodes sont de puissantes fonctionnalités Lua qui permettent des fonctionnalités telles que -
Modification / ajout de fonctionnalités aux opérateurs sur les tables.
Recherche de métatables lorsque la clé n'est pas disponible dans la table à l'aide de __index dans métatable.
Il existe deux méthodes importantes utilisées pour gérer les métatables, notamment:
setmetatable(table,metatable) - Cette méthode est utilisée pour définir métatable pour une table.
getmetatable(table) - Cette méthode est utilisée pour obtenir la métatable d'une table.
Voyons d'abord comment définir une table comme métatable d'une autre. Il est montré ci-dessous.
mytable = {}
mymetatable = {}
setmetatable(mytable,mymetatable)
Le code ci-dessus peut être représenté sur une seule ligne comme indiqué ci-dessous.
mytable = setmetatable({},{})
_indice
Un exemple simple de métatable permettant de rechercher la méta-table lorsqu'elle n'est pas disponible dans le tableau est illustré ci-dessous.
mytable = setmetatable({key1 = "value1"}, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return mytable[key]
end
end
})
print(mytable.key1,mytable.key2)
Lorsque nous exécutons le programme ci-dessus, nous obtiendrons la sortie suivante.
value1 metatablevalue
Expliquons par étapes ce qui s'est passé dans l'exemple ci-dessus.
Le tableau mytable ici est {key1 = "value1"}.
Metatable est défini pour mytable qui contient une fonction pour __index, que nous appelons une métaméthode.
La métaméthode fait un simple travail de recherche d'un index "key2", s'il est trouvé, il retourne "metatablevalue", sinon retourne la valeur de mytable pour l'index correspondant.
Nous pouvons avoir une version simplifiée du programme ci-dessus comme indiqué ci-dessous.
mytable = setmetatable({key1 = "value1"},
{ __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)
__newindex
Lorsque nous ajoutons __newindex à metatable, si les clés ne sont pas disponibles dans la table, le comportement des nouvelles clés sera défini par des méta-méthodes. Un exemple simple où l'index de metatable est défini lorsque l'index n'est pas disponible dans la table principale est donné ci-dessous.
mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "new value 2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "new value 1"
print(mytable.key1,mymetatable.newkey1)
Lorsque vous exécutez le programme ci-dessus, vous obtenez la sortie suivante.
value1
nil new value 2
new value 1 nil
Vous pouvez voir dans le programme ci-dessus, si une clé existe dans la table principale, elle la met simplement à jour. Lorsqu'une clé n'est pas disponible dans le maintable, il ajoute cette clé au métatable.
Un autre exemple qui met à jour la même table à l'aide de la fonction rawset est illustré ci-dessous.
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)
Lorsque nous exécutons le programme ci-dessus, nous obtiendrons la sortie suivante.
new value "4"
rawset définit la valeur sans utiliser __newindex de métatable. De même, il y a rawget qui obtient de la valeur sans utiliser __index.
Ajout d'un comportement d'opérateur aux tables
Un exemple simple pour combiner deux tables à l'aide de l'opérateur + est présenté ci-dessous -
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
Lorsque nous exécutons le programme ci-dessus, nous obtiendrons la sortie suivante.
1 1
2 2
3 3
4 4
5 5
6 6
La clé __add est incluse dans la métatable pour ajouter le comportement de operator +. Le tableau des touches et de l'opérateur correspondant est présenté ci-dessous.
N ° Sr. | Mode et description |
---|---|
1 | __add Modifie le comportement de l'opérateur «+». |
2 | __sub Modifie le comportement de l'opérateur «-». |
3 | __mul Modifie le comportement de l'opérateur «*». |
4 | __div Modifie le comportement de l'opérateur «/». |
5 | __mod Modifie le comportement de l'opérateur '%'. |
6 | __unm Modifie le comportement de l'opérateur «-». |
sept | __concat Modifie le comportement de l'opérateur «..». |
8 | __eq Modifie le comportement de l'opérateur '=='. |
9 | __lt Modifie le comportement de l'opérateur «<». |
dix | __le Modifie le comportement de l'opérateur '<='. |
__appel
L'ajout du comportement de l'appel de méthode se fait à l'aide de l'instruction __call. Un exemple simple qui renvoie la somme des valeurs de la table principale avec la table passée.
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))
Lorsque nous exécutons le programme ci-dessus, nous obtiendrons la sortie suivante.
70
__tostring
Pour modifier le comportement de l'instruction d'impression, nous pouvons utiliser la métaméthode __tostring. Un exemple simple est présenté ci-dessous.
mytable = setmetatable({ 10, 20, 30 }, {
__tostring = function(mytable)
sum = 0
for k, v in pairs(mytable) do
sum = sum + v
end
return "The sum of values in the table is " .. sum
end
})
print(mytable)
Lorsque nous exécutons le programme ci-dessus, nous obtiendrons la sortie suivante.
The sum of values in the table is 60
Si vous connaissez parfaitement les capacités de la méta-table, vous pouvez vraiment effectuer de nombreuses opérations qui seraient très complexes sans l'utiliser. Alors, essayez de travailler davantage sur l'utilisation des métatables avec différentes options disponibles dans les méta-tables comme expliqué dans les exemples et créez également vos propres échantillons.