Constructeurs et new()
Écrivez des fonctions constructrices qui créent et initialisent des instances.
Constructeurs et new() est une leçon Lua Academy gratuite sur CoddyKit. Ceci est la leçon 2 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.
Responsabilité du constructeur
Un constructeur crée et initialise une instance. Il reçoit les valeurs initiales, les valide, définit les valeurs par défaut des champs manquants et renvoie la nouvelle instance. Un constructeur bien conçu garantit que chaque instance commence dans un état valide.
local Player = {}
Player.__index = Player
function Player.new(name, hp, mp)
assert(type(name)=="string" and name~="","need name")
return setmetatable({
name = name,
hp = hp or 100,
mp = mp or 50,
alive = true,
items = {},
}, Player)
end
local p = Player.new("Hero")
print(p.name, p.hp, p.mp) -- Hero 100 50Constructeur fluide
Un constructeur fluide renvoie self depuis les méthodes de définition, ce qui permet d'enchaîner les méthodes lors de la construction. Il s'agit d'un modèle de conception de générateur en Lua.
local Config = {}
Config.__index = Config
function Config.new()
return setmetatable({_data={}}, Config)
end
function Config:set(k,v) self._data[k]=v; return self end
function Config:build() return self._data end
local cfg = Config.new()
:set("host","localhost")
:set("port",8080)
:set("debug",true)
:build()
print(cfg.host, cfg.port)Constructeur de copie
Un constructeur de copie crée une nouvelle instance avec les mêmes valeurs qu'une instance existante. Important : utilisez une copie superficielle ou profonde selon que les tables imbriquées doivent être partagées ou indépendantes.
local function deepCopy(orig)
if type(orig)~="table" then return orig end
local copy = {}
for k,v in pairs(orig) do copy[deepCopy(k)]=deepCopy(v) end
return setmetatable(copy, getmetatable(orig))
end
local Item = {}
Item.__index = Item
function Item.new(name, stats)
return setmetatable({name=name, stats=stats or {}}, Item)
end
function Item:clone()
return deepCopy(self)
end
local sword = Item.new("Sword",{damage=50})
local clone = sword:clone()
clone.stats.damage = 30
print(sword.stats.damage) -- 50 (unchanged)Constructeur avec validation
Validez toujours les entrées du constructeur. Déclenchez des erreurs descriptives pour les entrées invalides au niveau 2 (la responsabilité revient à l'appelant). Cela permet de détecter rapidement les bogues et de produire des messages d'erreur utiles.
local Rectangle = {}
Rectangle.__index = Rectangle
function Rectangle.new(w, h)
assert(type(w)=="number" and w>0,"width must be positive number")
assert(type(h)=="number" and h>0,"height must be positive number")
return setmetatable({width=w, height=h}, Rectangle)
end
function Rectangle:area() return self.width * self.height end
function Rectangle:perimeter() return 2*(self.width+self.height) end
local r = Rectangle.new(5, 3)
print(r:area(), r:perimeter()) -- 15 16Modèle des valeurs par défaut
Utilisez une table de valeurs par défaut pour gérer proprement les paramètres facultatifs du constructeur. Cela évite les longues chaînes de x = x or default et rend les valeurs par défaut explicites et faciles à modifier.
local Sprite = {}
Sprite.__index = Sprite
local DEFAULTS = {x=0,y=0,rotation=0,scale=1,visible=true,alpha=1}
function Sprite.new(image, opts)
local cfg = opts or {}
local self = {image=image}
for k,v in pairs(DEFAULTS) do
self[k] = cfg[k] ~= nil and cfg[k] or v
end
return setmetatable(self, Sprite)
end
local s = Sprite.new("hero.png",{x=100,y=200})
print(s.x,s.y,s.scale) -- 100 200 1Méthodes de fabrique statiques
Une classe peut disposer de plusieurs méthodes de fabrique pour différents scénarios de création. C'est plus propre que de surcharger un seul constructeur avec de nombreux paramètres facultatifs.
local Color = {}
Color.__index = Color
function Color.fromRGB(r,g,b)
return setmetatable({r=r,g=g,b=b}, Color)
end
function Color.fromHex(hex)
hex = hex:gsub("#","")
return setmetatable({
r=tonumber(hex:sub(1,2),16),
g=tonumber(hex:sub(3,4),16),
b=tonumber(hex:sub(5,6),16),
}, Color)
end
function Color:toHex()
return string.format("#%02X%02X%02X",self.r,self.g,self.b)
end
local red = Color.fromHex("#FF0000")
print(red:toHex()) -- #FF0000Registre des constructeurs
Utilisez un registre pour suivre toutes les instances. Cela permet d'effectuer des opérations globales comme « détruire tout » ou de parcourir tous les objets d'un type donné.
local Enemy = {}
Enemy.__index = Enemy
Enemy._all = {}
function Enemy.new(name, hp)
local self = setmetatable({name=name, hp=hp}, Enemy)
Enemy._all[#Enemy._all+1] = self
return self
end
function Enemy.destroyAll()
for _, e in ipairs(Enemy._all) do
print("Destroying:", e.name)
end
Enemy._all = {}
end
Enemy.new("Goblin",30)
Enemy.new("Orc",80)
print("Count:", #Enemy._all) -- 2
Enemy.destroyAll()Initialisation différée
Certains champs sont coûteux à calculer. Utilisez __index avec une fonction pour les calculer et les mettre en cache lors du premier accès.
local BigData = {}
BigData.__index = function(t, k)
if k == "processed" then
print("Computing processed...")
local result = {}
for i,v in ipairs(rawget(t,"raw")) do result[i]=v*2 end
rawset(t,"processed",result)
return result
end
end
function BigData.new(raw)
return setmetatable({raw=raw}, BigData)
end
local d = BigData.new({1,2,3,4,5})
print(d.processed[3]) -- Computing... 6
print(d.processed[3]) -- 6 (cached, no recompute)Prototype à partir d'une instance
Clonez une instance pour en créer une autre avec les mêmes valeurs de base. Le clone reçoit la même métatable (la même classe) ainsi qu'une copie des données de l'instance. C'est utile pour les objets « modèles ».
local Unit = {}
Unit.__index = Unit
function Unit.new(t)
return setmetatable({name=t.name,hp=t.hp,atk=t.atk}, Unit)
end
function Unit:clone()
return Unit.new({name=self.name,hp=self.hp,atk=self.atk})
end
function Unit:__tostring()
return self.name.."(HP:"..self.hp..",ATK:"..self.atk..")"
end
local template = Unit.new({name="Soldier",hp=100,atk=10})
local u1 = template:clone(); u1.name="Alpha"
local u2 = template:clone(); u2.name="Beta"
print(tostring(u1),tostring(u2))Sécurité du constructeur en cas d'erreur
Si la construction échoue en cours de route (par exemple lors de l'allocation d'une ressource), veillez à ce qu'aucun objet partiellement créé ne s'échappe. Utilisez pcall pour intercepter les erreurs de construction et libérer les ressources si nécessaire.
local FileHandle = {}
FileHandle.__index = FileHandle
function FileHandle.new(path, mode)
local f, err = io.open(path, mode or "r")
if not f then
return nil, "cannot open " .. path .. ": " .. err
end
return setmetatable({_f=f, path=path}, FileHandle)
end
function FileHandle:read(fmt) return self._f:read(fmt) end
function FileHandle:close() self._f:close() end
local fh, err = FileHandle.new("data.txt")
if not fh then print("Error:", err)
else print(fh:read("l")); fh:close()
endVérification rapide
Quel est le rôle d'un constructeur (new()) en POO Lua ?
Récapitulatif : constructeurs
Résumé :
- Le constructeur valide, initialise et appelle setmetatable
- Utilisez une table de valeurs par défaut pour gérer proprement les paramètres facultatifs
- Utilisez plusieurs méthodes de fabrique pour différents scénarios de création
- Utilisez un constructeur de clonage pour les objets modèles
- Utilisez l'initialisation différée via __index pour les champs coûteux
- En cas d'échec, renvoyez nil+err depuis le constructeur (allocation de ressource)
Questions Fréquemment Posées
La leçon « Constructeurs et new() » est-elle gratuite ?
Oui — le texte complet de « Constructeurs et new() » 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 « Constructeurs et new() » ?
Écrivez des fonctions constructrices qui créent et initialisent des instances. 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 2 sur 4.
Combien de temps prend la leçon « Constructeurs et new() » ?
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
- Classes via les métatables
- Constructeurs et new()
- Méthodes d’instance et self
- Encapsulation avec des fermetures