Lua Academy · Leçon

Redéfinition et polymorphisme

Redéfinissez les méthodes parentes et obtenez une distribution polymorphe à l’exécution.

Leçon 4 sur 412 étapes

Redéfinition et polymorphisme est une leçon Lua Academy gratuite sur CoddyKit. Ceci est la leçon 4 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.

Redéfinition de méthode

Une classe enfant redéfinit une méthode parente en définissant une méthode portant le même nom. Lorsqu'elle est appelée sur une instance enfant, c'est la version de l'enfant qui s'exécute. La version parente reste accessible via Parent.method(self).

local Shape={} Shape.__index=Shape
function Shape:area() return 0 end
function Shape:describe() print(type(self).." area="..self:area()) end

local Circle={} Circle.__index=Circle
setmetatable(Circle,{__index=Shape})
function Circle.new(r) return setmetatable({r=r},Circle) end
function Circle:area() return math.pi*self.r^2 end

local Square={} Square.__index=Square
setmetatable(Square,{__index=Shape})
function Square.new(s) return setmetatable({s=s},Square) end
function Square:area() return self.s^2 end

Circle.new(5):describe()
Square.new(4):describe()

Dispatch polymorphe

Polymorphisme : différents types d'objets répondent différemment au même message. Une fonction qui accepte toute « forme » et appelle :area() fonctionne avec tout type de forme : chacune répond avec sa propre implémentation.

local shapes={
  Circle.new(3),
  Square.new(4),
  Circle.new(1),
}

local total=0
for _,shape in ipairs(shapes) do
  total=total+shape:area()
end
print(string.format("Total area: %.2f",total))

Typage canard

Lua utilise le typage canard : si un objet possède la méthode, cela fonctionne. Aucune déclaration formelle d'interface n'est nécessaire. Une fonction qui appelle :speak() fonctionne avec tout objet possédant une méthode speak, quelle que soit sa classe.

local function makeNoise(obj)
  if type(obj.speak)=="function" then
    obj:speak()
  else
    print("(silent)")
  end
end

local Duck={speak=function(self) print("Quack!") end}
local Robot={speak=function(self) print("Beep boop!") end}
local Rock={}

makeNoise(Duck)   -- Quack!
makeNoise(Robot)  -- Beep boop!
makeNoise(Rock)   -- (silent)

Polymorphisme des opérateurs

Les métaméthodes comme __add permettent le polymorphisme des opérateurs. Différents types peuvent répondre à + selon leur propre sémantique, à condition de définir __add.

local Vec2={} Vec2.__index=Vec2
Vec2.__add=function(a,b) return Vec2.new(a.x+b.x,a.y+b.y) end
Vec2.__tostring=function(v) return "("..v.x..","..v.y..")" end
function Vec2.new(x,y) return setmetatable({x=x,y=y},Vec2) end

local Color={} Color.__index=Color
Color.__add=function(a,b)
  return Color.new(math.min(255,a.r+b.r),math.min(255,a.g+b.g),math.min(255,a.b+b.b))
end
function Color.new(r,g,b) return setmetatable({r=r,g=g,b=b},Color) end

print(tostring(Vec2.new(1,2)+Vec2.new(3,4)))  -- (4,6)

Patron visiteur

Le patron visiteur sépare les opérations des objets. Une opération « visite » des objets de différents types et appelle la méthode appropriée selon le type. Utilisez-le lorsque les opérations doivent varier selon le type sans modifier les types eux-mêmes.

local function printInfo(obj)
  local mt = getmetatable(obj)
  if mt == Circle then
    print(string.format("Circle r=%.1f area=%.2f",obj.r,obj:area()))
  elseif mt == Square then
    print(string.format("Square s=%.1f area=%.2f",obj.s,obj:area()))
  end
end
for _,s in ipairs({Circle.new(3),Square.new(4)}) do
  printInfo(s)
end

Tableau d'interface

Définissez une interface comme un tableau de noms de méthodes. Vérifiez qu'un objet implémente toutes les méthodes requises avant de l'utiliser de manière polymorphe.

local function implements(obj, interface)
  for _, method in ipairs(interface) do
    if type(obj[method]) ~= "function" then
      return false, "missing: "..method
    end
  end
  return true
end

local Drawable = {"draw","resize","move"}

local Widget = {
  draw=function(self) print("draw "..self.type) end,
  resize=function(self,w,h) self.w,self.h=w,h end,
  move=function(self,x,y) self.x,self.y=x,y end,
  type="button"
}

local ok,err = implements(Widget,Drawable)
print(ok,err)  -- true nil

Vérification de l'existence d'une méthode

Avant d'appeler une méthode facultative de manière polymorphe, vérifiez que l'objet la possède. Cela permet des capacités facultatives sans exiger de classe de base commune.

local function maybeUpdate(obj, dt)
  if type(obj.update)=="function" then
    obj:update(dt)
  end
end

local objects={
  {x=0,y=0,update=function(self,dt) self.x=self.x+10*dt end},
  {x=0,y=0},  -- no update
  {x=0,y=0,update=function(self,dt) self.y=self.y+5*dt end},
}

for _,o in ipairs(objects) do maybeUpdate(o,1) end
for _,o in ipairs(objects) do print(o.x,o.y) end

Tableau de dispatch selon le type

Au lieu d'enchaîner les conditions if/elseif, utilisez un tableau de dispatch : associez les noms de types à des fonctions gestionnaires. Il s'agit du patron de polymorphisme piloté par tableau.

local handlers={
  number  = function(v) return "num:"..v end,
  string  = function(v) return "str:\"".."..v.."\"" end,
  boolean = function(v) return "bool:"..(v and "T" or "F") end,
  table   = function(v) return "tbl:#"..tostring(#v) end,
}

local function describe(v)
  local h=handlers[type(v)]
  return h and h(v) or "unknown"
end

print(describe(42))
print(describe("hello"))
print(describe({1,2,3}))

Retours covariants

Les méthodes enfants peuvent renvoyer des types plus spécifiques que les méthodes parentes (retour covariant). Lua étant à typage dynamique, cela se fait naturellement : la fabrique de l'enfant renvoie une instance enfant, et pas seulement une instance parente.

local Base={} Base.__index=Base
function Base.new() return setmetatable({type="base"},Base) end
function Base:copy() return Base.new() end

local Child={} Child.__index=Child
setmetatable(Child,{__index=Base})
function Child.new(extra)
  local self=setmetatable({type="child"},Child)
  self.extra=extra; return self
end
function Child:copy() return Child.new(self.extra) end  -- covariant

local c=Child.new("hello")
local c2=c:copy()
print(c2.extra,getmetatable(c2)==Child)  -- hello true

Résumé du polymorphisme

Le polymorphisme en pratique dans Lua : un même nom de méthode, un comportement différent selon le type. Il s'obtient grâce à la programmation orientée objet fondée sur les métatables, aux vérifications de typage canard ou aux tableaux de dispatch. Aucun système formel d'interface n'est nécessaire : il suffit de conventions cohérentes de nommage des méthodes.

-- Three ways to achieve polymorphism:
-- 1. Metatable inheritance + method override
-- 2. Duck typing: just call it if it exists
-- 3. Dispatch table: map type -> handler

local function area(shape)
  -- Duck typing approach:
  assert(type(shape.area)=="function","needs area()")
  return shape:area()
end

print(area({area=function() return 16 end}))  -- 16

Question sur le polymorphisme

Comment fonctionne le polymorphisme dans Lua ?

Récapitulatif : redéfinition et polymorphisme

Redéfinissez les méthodes parentes dans la classe enfant. Lua résout les appels de bas en haut à travers la chaîne __index, ce qui permet naturellement un dispatch polymorphe à l'exécution.

Gratuit pour commencer

Apprends Lua avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
40
Leçons
159

Questions Fréquemment Posées

La leçon « Redéfinition et polymorphisme » est-elle gratuite ?

Oui — le texte complet de « Redéfinition et polymorphisme » 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 « Redéfinition et polymorphisme » ?

Redéfinissez les méthodes parentes et obtenez une distribution polymorphe à l’exécution. 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 4 sur 4.

Combien de temps prend la leçon « Redéfinition et polymorphisme » ?

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. Héritage simple avec chaînage de __index
  2. Appeler les méthodes parentes avec super
  3. Modèles de mixins
  4. Redéfinition et polymorphisme
← Retour à Lua Academy