0Pricing
Lua Academy · Leçon

Méthodes d’instance et self

Définissez des méthodes avec la syntaxe utilisant deux-points et le paramètre self implicite.

Méthodes d’instance et self 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.

self est l'instance

Lorsque vous appelez obj:method(), Lua transmet automatiquement obj comme premier argument. Par convention, ce paramètre est nommé self. Grâce à self, la méthode accède aux données de l'instance et appelle d'autres méthodes.

local Counter = {}
Counter.__index = Counter

function Counter.new(start)
  return setmetatable({value=start or 0, step=1}, Counter)
end

function Counter:increment()
  self.value = self.value + self.step
end

function Counter:getValue() return self.value end

local c = Counter.new(10)
c:increment(); c:increment()
print(c:getValue())  -- 12

Enchaînement des méthodes

Renvoyez self depuis les méthodes pour permettre l'enchaînement : obj:method1():method2():method3(). Chaque appel renvoie le même objet, ce qui permet un style fluide. Cette technique convient particulièrement aux méthodes qui modifient l'état.

local Builder = {}
Builder.__index = Builder

function Builder.new()
  return setmetatable({parts={}},Builder)
end

function Builder:add(s) self.parts[#self.parts+1]=s; return self end
function Builder:addAll(t)
  for _,v in ipairs(t) do self.parts[#self.parts+1]=v end
  return self
end
function Builder:build() return table.concat(self.parts," ") end

local result = Builder.new()
  :add("Hello")
  :add("from")
  :addAll({"Lua","OOP"})
  :build()
print(result)  -- Hello from Lua OOP

Appel d'autres méthodes

Les méthodes peuvent appeler d'autres méthodes sur la même instance via self:otherMethod(). Cela favorise la réutilisation du code au sein d'une classe. Les assistants privés peuvent être de simples fonctions locales qui reçoivent explicitement self.

local Stack = {}
Stack.__index = Stack

function Stack.new() return setmetatable({_data={},_size=0},Stack) end
function Stack:push(v) self._size=self._size+1; self._data[self._size]=v end
function Stack:pop()
  if self:isEmpty() then return nil end
  local v=self._data[self._size]; self._data[self._size]=nil
  self._size=self._size-1; return v
end
function Stack:peek()
  return not self:isEmpty() and self._data[self._size] or nil
end
function Stack:isEmpty() return self._size==0 end
function Stack:size() return self._size end

local s=Stack.new(); s:push(1);s:push(2);s:push(3)
print(s:pop(),s:peek(),s:size())  -- 3  2  2

Attention à la redéfinition d'une méthode

Définir dans une instance un champ portant le même nom qu'une méthode de classe masque cette méthode pour cette instance. Il s'agit généralement d'un bogue : soyez prudent lorsque les noms des champs d'instance peuvent entrer en conflit avec ceux des méthodes.

local Dog = {}
Dog.__index = Dog
function Dog.new(n) return setmetatable({name=n},Dog) end
function Dog:speak() print(self.name..": Woof!") end

local d = Dog.new("Rex")
d:speak()        -- Rex: Woof!

-- Accidental shadow:
d.speak = "loud"  -- now d.speak is a string, not a function
local ok,err = pcall(function() d:speak() end)
print(ok, err)   -- false  attempt to call a string value

self dans les fonctions de rappel

Passer une méthode comme fonction de rappel fait perdre le self implicite. Encapsulez la méthode dans une fermeture pour capturer self.

local Timer = {}
Timer.__index = Timer
function Timer.new(n) return setmetatable({count=n},Timer) end
function Timer:tick()
  self.count=self.count-1
  print("Ticking, count:", self.count)
end

local t = Timer.new(3)

-- Wrong: loses self
-- local cb = t.tick  -- cb(t) works but cb() doesn't

-- Correct: closure captures self
local cb = function() t:tick() end
cb(); cb(); cb()  -- Ticking 3 times

Méthodes statiques et méthodes d'instance

Une méthode statique est appelée sur la classe, et non sur une instance. Elle ne possède pas de self (ou reçoit la classe comme self). En Lua, il n'existe pas de distinction formelle : par convention, utilisez . (et non :) pour les méthodes statiques.

local MathUtils = {}
MathUtils.__index = MathUtils

-- Static method (no instance needed)
function MathUtils.clamp(v, lo, hi)
  return math.max(lo, math.min(hi, v))
end

-- Instance method (needs self)
function MathUtils:scale(factor)
  self.value = self.value * factor
end

print(MathUtils.clamp(15, 0, 10))  -- 10
local m = setmetatable({value=5},MathUtils)
m:scale(3)
print(m.value)  -- 15

Méthodes de mixin

Ajoutez les méthodes d'une table de mixin à une classe sans héritage formel. Il s'agit d'une composition à plat : copiez ou référencez les fonctions du mixin dans la table de la classe.

local Serializable = {}
function Serializable:serialize()
  local parts={}
  for k,v in pairs(self) do
    if type(v)~="function" then
      parts[#parts+1]=k.."="..tostring(v)
    end
  end
  return "{"..table.concat(parts,",").."}"
end

local User = {}
User.__index = User
User.serialize = Serializable.serialize   -- mixin!

function User.new(n,a) return setmetatable({name=n,age=a},User) end

local u = User.new("Alice",30)
print(u:serialize())

Méthodes abstraites

Lua n'impose pas les méthodes abstraites, mais vous pouvez définir dans une classe de base une méthode qui déclenche une erreur, obligeant les sous-classes à la redéfinir. C'est une convention indiquant qu'une méthode « doit être redéfinie ».

local Shape = {}
Shape.__index = Shape

function Shape.new() return setmetatable({},Shape) end

function Shape:area()
  error(type(self).." must implement area()",2)
end

function Shape:describe()
  print("Shape area:", self:area())
end

local sq={}
setmetatable(sq,{__index=Shape})
function sq:area() return 4*4 end

sq:describe()  -- Shape area: 16

Tables de méthodes

Pour les classes qui possèdent de nombreuses méthodes, organisez-les en groupes par fonctionnalité. Toutes les méthodes d'une même table utilisent la même recherche dans la métatable, mais vous pouvez les répartir par responsabilité au moyen de sous-espaces de noms.

local Entity = {}
Entity.__index = Entity

Entity.Physics = {}
function Entity.Physics:applyForce(fx,fy)
  self.vx=(self.vx or 0)+fx
  self.vy=(self.vy or 0)+fy
end

Entity.Render = {}
function Entity.Render:draw()
  print(string.format("Draw at (%g,%g)",self.x or 0,self.y or 0))
end

-- Mix into main class
for k,v in pairs(Entity.Physics) do Entity[k]=v end
for k,v in pairs(Entity.Render) do Entity[k]=v end

function Entity.new(x,y) return setmetatable({x=x,y=y},Entity) end
local e=Entity.new(10,20); e:draw(); e:applyForce(5,0); print(e.vx)

Délégation ou héritage

Préférez la délégation (conserver une référence) aux longues chaînes d'héritage. Une classe peut déléguer à un autre objet au lieu d'en hériter, ce qui limite le couplage et permet à chaque classe de rester ciblée.

local Logger = {}
Logger.__index = Logger
function Logger.new(name) return setmetatable({name=name},Logger) end
function Logger:log(msg) print("["..self.name.."] "..msg) end

local Service = {}
Service.__index = Service

function Service.new(name)
  return setmetatable({
    name=name,
    logger=Logger.new(name)  -- delegation
  },Service)
end

function Service:start()
  self.logger:log("starting...")  -- delegate logging
  print(self.name, "running")
end

Service.new("AuthService"):start()

Vérification rapide

Quelle est la différence entre obj:method() et obj.method() ?

Récapitulatif : méthodes d'instance

Résumé :

  • Syntaxe d'appel avec deux-points : obj:method() == obj.method(obj)
  • Renvoyez self pour enchaîner les méthodes
  • Appelez d'autres méthodes : self:otherMethod()
  • Fonctions de rappel : encapsulez-les dans une fermeture pour préserver self
  • Méthodes statiques : utilisez la notation avec un point par convention
  • Préférez la délégation à l'héritage profond pour plus de souplesse

Questions Fréquemment Posées

La leçon « Méthodes d’instance et self » est-elle gratuite ?

Oui — le texte complet de « Méthodes d’instance et self » 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éthodes d’instance et self » ?

Définissez des méthodes avec la syntaxe utilisant deux-points et le paramètre self implicite. 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éthodes d’instance et self » ?

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. Classes via les métatables
  2. Constructeurs et new()
  3. Méthodes d’instance et self
  4. Encapsulation avec des fermetures
← Retour à Lua Academy