{}const=>[]async()letfn</>var
LuaDéveloppement

Metatables en Lua : la simplicité de la complexité

Voyons ce que sont les metatables dans Lua, pourquoi ils sont nécessaires et comment les utiliser pour ajouter des « superpouvoirs » aux tables.

К

Kodik

Auteur

4 min de lecture

Nous voulons souvent que les tableaux se comportent « d'une manière spéciale » : qu'ils s'additionnent comme des vecteurs, qu'ils remplacent les valeurs par défaut, qu'ils s'impriment magnifiquement. ✨ Pour cela, Lua a metatables - scénaristes cachés du comportement des tableaux. Ci-dessous, une analyse brève, pratique et indolore.

🧩 Que sont les metatables

Metatable — il s'agit d'une table ordinaire attachée à une autre table via setmetatable(), qui décrit comment l'objet réagit aux opérations : indexation, addition, comparaison, concaténation, appel, etc.

Considérez la métatable comme une « couche de règles » : Lua vérifie les clés et les opérations et, s'il trouve une métaméthode correspondante (par exemple, __index), il l'utilise.

🧰 Pourquoi est-ce nécessaire

Tâche

Métaméthode

Valeurs par défaut/prototype

__index

Contrôle / interdiction d'enregistrement

__newindex

Redéfinition de l'addition / multiplication / ...

__add, __mul, …

Belle conclusion

__tostring

Comparaison / longueur / concaténation

__eq, __lt, __len, __concat

Créons un tableau « appelé »

__call

Protéger la métatable

__metatable

🔥 100 000+ étudiants déjà avec nous

Marre de lire la théorie ?
Il est temps de coder !

Kodik — une appli où tu apprends à coder par la pratique. Mentor IA, leçons interactives, projets réels.

🤖 IA 24/7
🎓 Certificats
💰 Gratuit
🚀 Commencer
Ont rejoint aujourd'hui

L'exemple le plus court : l'addition de tableaux en tant que vecteurs

local mt = {
  __add = function(a, b)
    return { a[1] + b[1], a[2] + b[2] }
  end
}

local v1 = setmetatable({1, 2}, mt)
local v2 = setmetatable({3, 4}, mt)

local sum = v1 + v2
print(sum[1], sum[2]) --> 4  6

Sans les métatables v1 + v2 cela provoquerait une erreur : Lua ne sait pas comment ajouter des tables.

🧭 __index : valeurs par défaut et « héritage »

__index se déclenche lorsqu'il n'y a pas de clé dans le tableau. Il peut être défini par une référence à une table prototype ou à une fonction.

Option 1 : prototype

local defaults = { speed = 10, hp = 100 }
local player = setmetatable({}, { __index = defaults })

print(player.speed)  --> 10 (берётся из defaults)
player.speed = 20    -- теперь свой speed у player
print(player.speed)  --> 20

Option 2 : création automatique de valeurs (initialisation paresseuse)

local counts = setmetatable({}, {
  __index = function(t, key)
    local v = 0
    rawset(t, key, v)     -- записываем сразу, чтобы дальше было «как будто существовало всегда»
    return v
  end
})

counts["apples"] = counts["apples"] + 1
print(counts["apples"]) --> 1

Nous utilisons rawset pour ne pas appeler __newindex et ne pas tomber dans la récursion.

🛡️ __newindex : contrôle de l'enregistrement

local guarded = setmetatable({ x = 0, y = 0 }, {
  __newindex = function(t, k, v)
    if k == "x" or k == "y" then
      rawset(t, k, v)              -- безопасная запись без повторного вызова __newindex
    else
      error("You cannot add a new field: " .. tostring(k), 2)
    end
  end
})

guarded.x = 10    -- ок
guarded.title = "oops"  -- ошибка

Une erreur courante est d'écrire t[k] = v à l'intérieur de __newindex. Cela appellera à nouveau __newindex et conduira à une récursion. Utilisez rawset.

⚠️ Pièges

  • Méta-tableaux ne sont pas copiés lors de la copie de surface du tableau, accrochez à nouveau.

  • Les chaînes trop astucieuses __index rendent le débogage difficile. Gardez le modèle simple.

  • rawget/rawset contourner les métaméthodes est à la fois une force et un risque. Utilisez-les consciemment.

🚀 Techniques avancées de Metatables

📞 __call : créer une « usine » d'objets

La métaméthode __call vous permet d'appeler une table en tant que fonction, ce qui est pratique pour les fabriques et les DSL.

local greeter = setmetatable({}, {
  __call = function(_, name) print("Hi, " .. name .. "!") end
})

greeter("Code") --> Привет, Кодик!

🔒 __metatable : protection contre les modifications

Vous pouvez cacher les métaméthodes réelles et interdire leur modification de la manière suivante :

local obj = {}
local mt  = { __metatable = "Access to the metatable is denied" }
setmetatable(obj, mt)

print(getmetatable(obj)) --> Доступ к метатаблице запрещён
-- getmetatable(obj).__index  -- уже не получить

🎨 Belle conclusion et opérateurs « magiques »

local mt = {
  __tostring = function(t) return ("Point(%d, %d)"):format(t.x, t.y) end,
  __len      = function(t) return math.sqrt(t.x*t.x + t.y*t.y) end, -- длина вектора через #
  __eq       = function(a,b) return a.x==b.x and a.y==b.y end,
  __add      = function(a,b) return setmetatable({x=a.x+b.x, y=a.y+b.y}, mt) end,
}
local p = setmetatable({x=3, y=4}, mt)
print(p)    --> Point(3, 4)
print(#p)   --> 5

💬 Où appliqueriez-vous les metatables : dans un jeu Roblox/Love2D, dans un système de configuration ou dans un mini‑DSL ?

📚 Vous voulez approfondir le sujet ?

Dans l'application Code vous trouverez des leçons détaillées sur Lua, des exercices étape par étape, des analyses d'erreurs et des exercices pratiques directement sur votre téléphone ou votre navigateur.

Et si vous voulez être au courant des nouveautés, des nouvelles fonctionnalités et des contenus utiles, abonnez-vous à notre Chaîne Telegram. C'est confortable, professionnel et avec amour pour le code ❤️

🎯Arrête de reporter

Tu as aimé l'article ?
Place à la pratique !

Avec Kodik, tu ne lis pas seulement — tu codes immédiatement. Théorie + pratique = vraies compétences.

Pratique instantanée
🧠L'IA explique le code
🏆Certificat

Sans inscription • Sans carte