Métaméthodes arithmétiques
Surchargez +, -, *, / et d’autres opérateurs avec des métaméthodes.
Métaméthodes arithmétiques est une leçon Lua Academy gratuite sur CoddyKit. Ceci est la leçon 3 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.
Noms des méthodes de métatable
Lua définit des méthodes de métatable pour tous les opérateurs arithmétiques. Lorsque Lua rencontre une opération arithmétique sur une table, il recherche la méthode de métatable correspondante dans la métatable de la table. Si les deux opérandes sont des tables, Lua vérifie d’abord la métatable de l’opérande de gauche.
-- Operator -> Metamethod
-- a + b -> __add
-- a - b -> __sub
-- a * b -> __mul
-- a / b -> __div
-- a % b -> __mod
-- a ^ b -> __pow
-- a // b -> __idiv
-- -a -> __unm (unary minus)
-- #a -> __len
print("Metamethods defined for all Lua operators")__add pour additionner des vecteurs
Définissez __add sur une table représentant un vecteur pour prendre en charge +. La méthode de métatable reçoit deux opérandes et renvoie une nouvelle valeur. Les deux opérandes peuvent être des tables, ou l’un d’eux peut être un nombre : votre méthode de métatable doit gérer ces deux cas.
local Vec = {}
Vec.__index = Vec
Vec.__add = function(a, b)
return setmetatable({x=a.x+b.x, y=a.y+b.y}, Vec)
end
Vec.__tostring = function(v)
return string.format("Vec(%g,%g)", v.x, v.y)
end
function Vec.new(x,y) return setmetatable({x=x,y=y},Vec) end
local v1 = Vec.new(1,2)
local v2 = Vec.new(3,4)
print(tostring(v1 + v2)) -- Vec(4,6)__sub __mul __div
Définissez __sub, __mul et __div de manière similaire. Pour la multiplication, gérez les cas table*table et table*nombre en vérifiant le type des opérandes dans la méthode de métatable.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__sub = function(a,b) return V(a.x-b.x, a.y-b.y) end
Vec.__mul = function(a,b)
if type(a)=="number" then return V(a*b.x, a*b.y)
elseif type(b)=="number" then return V(a.x*b, a.y*b)
else return a.x*b.x + a.y*b.y -- dot product
end
end
Vec.__tostring=function(v) return "("..v.x..","..v.y..")" end
local v = V(3,4)
print(tostring(v * 2)) -- (6,8)
print(tostring(V(1,0) - V(0,1))) -- (1,-1)__unm : moins unaire
__unm est la méthode de métatable du moins unaire, appelée lorsque Lua évalue -obj. Elle reçoit l’opérande (la même valeur lui est transmise deux fois par cohérence) et renvoie la valeur opposée.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__unm = function(a) return V(-a.x, -a.y) end
Vec.__tostring = function(v)
return string.format("(%g,%g)", v.x, v.y)
end
local v = V(3, -4)
print(tostring(-v)) -- (-3,4)
print(tostring(-(-v))) -- (3,-4)__len pour une longueur personnalisée
__len est appelée lors de l’évaluation de #obj sur une table dépourvue de séquence entière brute. Définissez-la pour renvoyer une « longueur » pertinente pour des types personnalisés tels que les ensembles, les files ou les conteneurs pondérés.
local Bag = {}
Bag.__index = Bag
Bag.__len = function(b) return b._count end
function Bag.new()
return setmetatable({_count=0, _items={}}, Bag)
end
function Bag:add(item, qty)
self._items[item] = (self._items[item] or 0) + (qty or 1)
self._count = self._count + (qty or 1)
end
local bag = Bag.new()
bag:add("apple", 3)
bag:add("banana", 2)
print(#bag) -- 5__mod et __pow
__mod gère l’opérateur % ; __pow gère ^. Ces méthodes sont moins courantes, mais utiles pour des types numériques personnalisés tels que les grands entiers, les fractions ou les objets d’arithmétique modulaire.
local Modular = {}
Modular.__index = Modular
local M = 1000000007
local function mod(n)
return setmetatable({n = n % M}, Modular)
end
Modular.__add = function(a,b) return mod(a.n + b.n) end
Modular.__mul = function(a,b) return mod(a.n * b.n) end
Modular.__pow = function(a,b)
local r, base, exp = mod(1), a, b
while exp > 0 do
if exp%2==1 then r = r*base end
base = base*base; exp = math.floor(exp/2)
end
return r
end
print((mod(2) ^ 30).n) -- 73741817 (2^30 mod 1e9+7)__concat
__concat est déclenchée par l’opérateur .. lorsqu’au moins un opérande possède cette méthode de métatable. Cela vous permet de définir la concaténation pour des types personnalisés ou de créer des langages spécifiques à un domaine avec une syntaxe fluide.
local Builder = {}
Builder.__index = Builder
Builder.__concat = function(a, b)
local result = {}
for _, v in ipairs(a._parts) do result[#result+1] = v end
if type(b) == "string" then result[#result+1] = b
else for _, v in ipairs(b._parts) do result[#result+1] = v end end
return setmetatable({_parts=result}, Builder)
end
Builder.build = function(b) return table.concat(b._parts) end
local function S(s) return setmetatable({_parts={s}},Builder) end
print((S("Hello") .. ", " .. S("World") .. "!"):build())Méthodes de métatable de comparaison
__eq définit == pour les tables (appelée uniquement lorsque les deux opérandes ont la même métatable). __lt définit < ; __le définit <=. Remarque : ~= utilise __eq ; > utilise __lt avec les arguments inversés ; >= utilise __le.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__eq = function(a,b) return a.x==b.x and a.y==b.y end
Vec.__lt = function(a,b)
return (a.x^2+a.y^2) < (b.x^2+b.y^2) -- by magnitude
end
print(V(1,2) == V(1,2)) -- true
print(V(1,2) == V(1,3)) -- false
print(V(1,0) < V(2,0)) -- true (1 < 2)Chaînage des méthodes de métatable
Comme les méthodes de métatable renvoient des valeurs (généralement de nouvelles tables), les opérations peuvent être enchaînées naturellement. Chaque opérateur renvoie un nouvel objet, et l’opérateur suivant utilise ce résultat. Cela permet d’écrire des expressions arithmétiques fluides sur des types personnalisés.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__add = function(a,b) return V(a.x+b.x,a.y+b.y) end
Vec.__mul = function(a,b)
if type(b)=="number" then return V(a.x*b,a.y*b) end
return V(a.x*b.x+a.y*b.y, 0) -- simplified
end
Vec.__tostring=function(v) return "("..v.x..","..v.y..")" end
local result = V(1,0) + V(0,1) * 3
print(tostring(result)) -- (1,3)Opérations entre types différents
Lorsque vous écrivez vec * 2, l’opérande de gauche est la table. Lorsque vous écrivez 2 * vec, l’opérande de gauche est un nombre (sans méthode de métatable), donc Lua vérifie la métatable de l’opérande de droite pour y trouver __mul. Gérez les deux ordres dans votre méthode de métatable.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__tostring = function(v) return "("..v.x..","..v.y..")" end
Vec.__mul = function(a, b)
if type(a) == "number" then
return V(a*b.x, a*b.y) -- scalar * vec
elseif type(b) == "number" then
return V(a.x*b, a.y*b) -- vec * scalar
end
return a.x*b.x + a.y*b.y -- dot product
end
print(tostring(V(1,2) * 3)) -- (3,6)
print(tostring(3 * V(1,2))) -- (3,6)Vérification rapide
Quelle méthode de métatable est déclenchée par -myTable ?
Récapitulatif : méthodes de métatable arithmétiques
Résumé :
__add __sub __mul __div __mod __pow __idiv— arithmétique binaire__unm— moins unaire ;__len— opérateur #__concat— opérateur..__eq __lt __le— opérateurs de comparaison- Gérez les types mixtes (nombre/table) dans les méthodes de métatable
Questions Fréquemment Posées
La leçon « Métaméthodes arithmétiques » est-elle gratuite ?
Oui — le texte complet de « Métaméthodes arithmétiques » 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 « Métaméthodes arithmétiques » ?
Surchargez +, -, *, / et d’autres opérateurs avec des métaméthodes. 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 3 sur 4.
Combien de temps prend la leçon « Métaméthodes arithmétiques » ?
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