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.