0Pricing
Lua Academy · Leçon

Introduction aux métatables

Définissez et récupérez des métatables avec setmetatable/getmetatable.

Introduction aux métatables est une leçon Lua Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Lua Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Lua Academy comprend 4 leçons au total.

Qu'est-ce qu'une metatable ?

Une metatable est une table Lua ordinaire qui contrôle le comportement d'une autre table. Lorsque Lua rencontre une opération qu'il ne peut pas effectuer sur une table (comme une opération arithmétique ou l'accès à une clé inexistante), il recherche la méthode de métatable correspondante dans la metatable. C'est le mécanisme d'extension de Lua pour la surcharge des opérateurs et la programmation orientée objet.

local t = {}
local mt = {__index = function(_, k) return "default_" .. k end}

setmetatable(t, mt)

print(t.foo)    -- default_foo
print(t.bar)    -- default_bar
print(t[1])     -- default_1

setmetatable et getmetatable

setmetatable(t, mt) définit la metatable de t sur mt et renvoie t. getmetatable(t) renvoie la metatable, ou nil s'il n'y en a aucune. Vous pouvez empêcher la modification d'une metatable en définissant mt.__metatable = "protected".

local t = {x = 10}
local mt = {}

setmetatable(t, mt)
print(getmetatable(t) == mt)   -- true

-- Protect metatable
mt.__metatable = "locked"
print(getmetatable(t))   -- locked
-- setmetatable(t, {})  -- ERROR: cannot change protected metatable

__index comme table

Lorsque __index est une table, Lua recherche la clé manquante dans cette table. C'est le fondement de l'héritage par prototypes de Lua. Si la clé ne se trouve pas non plus dans __index, Lua vérifie la metatable de celle-ci, et ainsi de suite le long de la chaîne.

local Animal = {sound = "...", legs = 4}

local Dog = setmetatable({sound = "Woof"}, {__index = Animal})
local Cat = setmetatable({sound = "Meow"}, {__index = Animal})

print(Dog.sound)   -- Woof (own field)
print(Dog.legs)    -- 4 (from Animal)
print(Cat.sound)   -- Meow
print(Cat.legs)    -- 4

__index comme fonction

Lorsque __index est une fonction, Lua l'appelle avec la table et la clé manquante. La fonction peut calculer la valeur ou la récupérer dynamiquement. Renvoyez nil depuis __index pour indiquer que la « clé est introuvable ».

local dynamic = setmetatable({}, {
  __index = function(t, k)
    if k:sub(1,4) == "get_" then
      local field = k:sub(5)
      return function(self) return self[field] end
    end
    return nil
  end
})

dynamic.name = "Lua"
local getter = dynamic.get_name
print(getter(dynamic))   -- Lua

rawget et rawset

rawget(t, k) lit une clé de table sans déclencher __index. rawset(t, k, v) définit une clé sans déclencher __newindex. Utilisez ces fonctions pour contourner les méthodes de métatable lorsque vous avez besoin d'un accès direct à une table depuis une méthode de métatable, afin d'éviter une récursion infinie.

local logged = setmetatable({}, {
  __newindex = function(t, k, v)
    print("Setting", k, "=", v)
    rawset(t, k, v)  -- bypass __newindex
  end
})

logged.x = 10   -- Setting x = 10
logged.x = 20   -- no log! key now exists in t
print(logged.x) -- 20

Plusieurs tables partageant une métatable

Une seule métatable peut être partagée par de nombreuses tables. C’est ainsi que fonctionnent les systèmes de classes de Lua : toutes les instances d’une classe partagent la même métatable, qui contient les méthodes. Les modifications apportées à la métatable affectent toutes les instances.

local Mt = {
  __index = {
    greet = function(self)
      print("Hello from " .. (self.name or "?"))
    end
  }
}

local a = setmetatable({name="Alice"}, Mt)
local b = setmetatable({name="Bob"},   Mt)

a:greet()   -- Hello from Alice
b:greet()   -- Hello from Bob

Champ __metatable

Définir mt.__metatable sur n’importe quelle valeur oblige getmetatable à renvoyer cette valeur au lieu de la métatable réelle. Cela empêche les utilisateurs d’inspecter ou de remplacer la métatable — ce qui est utile pour l’encapsulation et la sécurité.

local secret = setmetatable({}, {
  __metatable = false,    -- hide metatable
  __index = {value = 42}
})

print(secret.value)        -- 42
print(getmetatable(secret)) -- false (not the real mt)
-- setmetatable(secret, {}) -- ERROR

Vérifier la présence d’une métatable

Utilisez getmetatable(t) pour vérifier qu’un objet possède une métatable spécifique (pour vérifier son type). Comme __metatable peut masquer la métatable réelle, utilisez rawequal ou un champ indicateur pour effectuer des vérifications fiables de type d’instance.

local MyClass = {}
MyClass.__index = MyClass
MyClass.__metatable = MyClass   -- use self as marker

function MyClass.new(x)
  return setmetatable({x=x}, MyClass)
end

local obj = MyClass.new(5)
print(getmetatable(obj) == MyClass)   -- true
print(obj.x)                           -- 5

Métatables sur les valeurs qui ne sont pas des tables

Les chaînes de caractères de Lua possèdent déjà une métatable (le module string). C’est pourquoi vous pouvez appeler s:upper() sur n’importe quelle chaîne. En Lua pur, vous ne pouvez pas définir de métatables sur les chaînes, les nombres ou les booléens — uniquement sur les tables et les données utilisateur.

local s = "hello"
local mt = getmetatable(s)

-- String metatable has __index = string library
print(mt.__index == string)   -- true

-- So all string functions are methods:
print(s:upper())              -- HELLO
print(s:rep(3, "-"))          -- hello-hello-hello

Déboguer avec des métatables

Vous pouvez ajouter une méthode de métatable __tostring pour contrôler la façon dont tostring() et print() affichent une table. C’est particulièrement précieux pour déboguer des objets complexes.

local Point = {}
Point.__index = Point
Point.__tostring = function(p)
  return string.format("Point(%g, %g)", p.x, p.y)
end

function Point.new(x, y)
  return setmetatable({x=x,y=y}, Point)
end

local p = Point.new(3, 4)
print(tostring(p))   -- Point(3, 4)
print(p)             -- Point(3, 4)  (print calls tostring)

Vérification rapide

Que se passe-t-il lorsque vous accédez à une clé introuvable dans une table dont la métatable possède un __index défini sur une autre table ?

Récapitulatif : métatables

Résumé :

  • setmetatable(t, mt) / getmetatable(t)
  • __index : table → recherche dans le prototype ; fonction → appel dynamique
  • rawget/rawset contournent les méthodes de métatable
  • Les métatables partagées permettent un comportement semblable à celui des classes
  • __metatable protège la métatable contre l’inspection
  • __tostring contrôle l’affichage par print

Questions Fréquemment Posées

La leçon « Introduction aux métatables » est-elle gratuite ?

Oui — le texte complet de « Introduction aux métatables » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Lua Academy, passe à CoddyKit PRO. Le cours Lua Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Introduction aux métatables » ?

Définissez et récupérez des métatables avec setmetatable/getmetatable. Tu pratiques Lua Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Lua Academy ?

Aucune expérience préalable n'est requise. Lua Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Introduction aux métatables » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Lua Academy ?

Oui. Chaque leçon Lua Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Introduction aux métatables
  2. __index et __newindex
  3. Métaméthodes arithmétiques
  4. __tostring et __len
← Retour à Lua Academy