0Pricing
Lua Academy · Leçon

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

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