Métatables et métaméthodes
Une métatable est une table ordinaire associée à une autre valeur (table, userdata, ou même un
type primitif) pour définir un comportement personnalisé — surcharge d'opérateurs, indexation par
défaut, etc. Ces fonctions font partie de la bibliothèque de base (stdlib/) mais leur sémantique
est décrite ici car elle fait partie du comportement du langage :
local Vecteur = {}
Vecteur.__index = Vecteur
Vecteur.__add = function(a, b) return setmetatable({ x = a.x + b.x, y = a.y + b.y }, Vecteur) end
Vecteur.__tostring = function(v) return "(" .. v.x .. "," .. v.y .. ")" end
local v1 = setmetatable({ x = 1, y = 2 }, Vecteur)
local v2 = setmetatable({ x = 3, y = 4 }, Vecteur)
local v3 = v1 + v2 -- invoque Vecteur.__add
getmetatable(v) / setmetatable(v, mt) lisent/posent la métatable d'une valeur (setmetatable
n'accepte qu'une table ou nil en table cible).
Événements supportés
| Événement | Déclenché par | Notes |
|---|---|---|
__index |
t.k / t[k] quand la clé est absente de t |
table (indexée à son tour) ou fonction (t, k) |
__newindex |
t.k = v quand la clé est absente de t |
table (l'écriture s'y répercute) ou fonction (t, k, v) |
__call |
t(...) où t n'est pas directement une fonction |
fonction (t, ...) |
__add __sub __mul __div __idiv __mod __pow |
+ - * / // % ^ |
fonction (a, b) |
__band __bor __bxor __shl __shr |
& | ~ (binaire) << >> |
fonction (a, b) |
__neg |
-x (unaire) |
fonction (x, x) |
__bnot |
~x (unaire) |
fonction (x, x) |
__eq |
==/~= entre deux valeurs de même type non trivialement égales |
fonction (a, b) retournant une valeur convertie en booléen |
__lt |
< (et > avec les opérandes inversés) |
fonction (a, b) |
__le |
<= (et >= avec les opérandes inversés) |
fonction (a, b) |
__len |
#v |
fonction (v, v) |
__concat |
.. quand un opérande n'est ni chaîne ni nombre |
fonction (a, b) |
__close |
fermeture d'une ressource | voir ci-dessous |
__gc |
passage au ramasse-miettes | voir ci-dessous |
__mode |
mode faible d'une table ("k", "v" ou "kv") |
chaîne, pas une fonction |
__tostring |
tostring(v) / print(v) |
fonction (v) retournant la chaîne d'affichage |
__pairs |
pairs(t) |
fonction (t) retournant 3 valeurs (itérateur, état, contrôle initial) |
Pour un opérateur binaire, l'événement est d'abord cherché sur la métatable du premier opérande, puis sur celle du second s'il n'y est pas trouvé.
__tostring et __pairs ne sont pas des opérateurs du langage (pas d'opcode VM dédié) : ce sont
tostring/print et pairs, dans la bibliothèque de base, qui consultent directement ce champ de
la métatable. Le résultat est le même qu'en Lua, juste implémenté au niveau bibliothèque plutôt que
par le mécanisme générique de dispatch des autres métaévénements ci-dessus — voir stdlib/base.md.
__index / __newindex
Base de la programmation « orientée objet » façon Lua : une table __index sert de table de
« classe » partagée par toutes les instances qui l'ont pour métatable.
local Animal = {}
Animal.__index = Animal
function Animal.new(nom) return setmetatable({ nom = nom }, Animal) end
function Animal:parler() print(self.nom .. " fait du bruit") end
local a = Animal.new("Rex")
a:parler() --> Rex fait du bruit (a.parler est absent, __index redirige vers Animal.parler)
Métatables de type primitif
setmetatable/getmetatable peuvent aussi cibler un type de valeur entier (par exemple toutes
les chaînes) plutôt qu'une valeur individuelle — voir la bibliothèque string (stdlib/) qui
s'appuie sur ce mécanisme pour permettre ("abc"):upper().
__close
Une variable locale déclarée avec l'attribut <close> invoque __close(valeur, erreur) sur sa
valeur en sortie de bloc (mécanisme « to-be-closed » de Lua 5.4) : fin de bloc normale, retour de
fonction, ou déroulement dû à une erreur qui traverse le bloc — erreur vaut alors l'objet
d'erreur en cours de propagation, sinon nil. La valeur doit être false, nil, ou posséder
__close : toute autre valeur lève une erreur immédiatement à la déclaration, pas seulement à la
fermeture. Plusieurs variables <close> d'un même bloc sont fermées dans l'ordre inverse de leur
déclaration. Voir Variables pour un exemple.
__gc
Invoquée par le ramasse-miettes lors de la collecte d'un objet référençant cette métatable — comportement non déterministe (pas de destruction déterministe en fin de bloc), à ne pas utiliser pour une logique devant s'exécuter à un instant précis.