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_1setmetatable 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)) -- Luarawget 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) -- 20Plusieurs 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 BobChamp __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, {}) -- ERRORVé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) -- 5Mé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-helloDé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 dynamiquerawget/rawsetcontournent les méthodes de métatable- Les métatables partagées permettent un comportement semblable à celui des classes
__metatableprotège la métatable contre l’inspection__tostringcontrô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
- Introduction aux métatables
- __index et __newindex
- Métaméthodes arithmétiques
- __tostring et __len