Aller au contenu principal
ShadowAcademy

Les langages / Lua / Metatables

Métatables - Introduction

Les métatables sont un mécanisme puissant qui permet de modifier le comportement des tables. Elles permettent de surcharger les opérateurs, créer des propriétés calculées, et implémenter l'héritage.

Créer et assigner une métatable

-- Table normale
local personne = {nom = "Shadow", age = 25}

-- Créer une métatable
local meta = {
  __tostring = function(t)
    return t.nom .. " (" .. t.age .. " ans)"
  end
}

-- Assigner la métatable
setmetatable(personne, meta)

-- Maintenant print() utilise __tostring
print(personne)  -- Shadow (25 ans)

-- Récupérer la métatable
local m = getmetatable(personne)
print(m == meta)  -- true

Surcharge d'opérateurs arithmétiques

-- Créer un vecteur 2D
local Vecteur = {}
Vecteur.__index = Vecteur

function Vecteur.new(x, y)
  local v = {x = x or 0, y = y or 0}
  setmetatable(v, Vecteur)
  return v
end

-- Surcharger l'addition
Vecteur.__add = function(a, b)
  return Vecteur.new(a.x + b.x, a.y + b.y)
end

-- Surcharger la multiplication
Vecteur.__mul = function(a, scalar)
  return Vecteur.new(a.x * scalar, a.y * scalar)
end

local v1 = Vecteur.new(3, 4)
local v2 = Vecteur.new(1, 2)
local v3 = v1 + v2  -- (4, 6)
local v4 = v1 * 2   -- (6, 8)

__index pour les propriétés manquantes

-- Table par défaut
local defauts = {
  langue = "fr",
  theme = "dark",
  notifications = true
}

-- Configuration utilisateur (incomplète)
local config = {
  langue = "en"
}

-- Utiliser defauts comme fallback
setmetatable(config, {__index = defauts})

print(config.langue)         -- en (défini)
print(config.theme)          -- dark (depuis defauts)
print(config.notifications)  -- true (depuis defauts)

-- Modifier ne change pas les défauts
config.theme = "light"
print(defauts.theme)  -- dark (inchangé)

__newindex pour contrôler les affectations

-- Table en lecture seule
local constantes = {PI = 3.14159, E = 2.71828}

local meta = {
  __index = constantes,
  __newindex = function(t, key, value)
    error("Tentative de modification d'une constante: " .. key, 2)
  end
}

local c = {}
setmetatable(c, meta)

print(c.PI)  -- 3.14159 (lecture OK)
-- c.PI = 3  -- ERREUR: modification interdite

-- Table avec validation
local joueur = {}
setmetatable(joueur, {
  __newindex = function(t, key, value)
    if key == "vie" and (value < 0 or value > 100) then
      error("Vie doit être entre 0 et 100")
    end
    rawset(t, key, value)
  end
})

2 exercices pour cette lecon

Les exercices demandent un compte : il faut bien enregistrer votre progression quelque part. La lecture, elle, reste libre. Creer un compte

  • Métatables - Introduction difficile 35 XP
  • Métatables - __add difficile 35 XP