Délégation
Fait partie de la section Object Oriented Programming du Journey Lua de Coddy — leçon 50 sur 70.
Stocker un objet à l'intérieur d'un autre objet n'est que la première étape. La véritable puissance de la composition provient de la délégation — lorsque l'objet externe transmet les appels de méthode à ses composants internes.
Imaginez que vous démarrez une voiture. Vous ne passez pas la main sous le capot pour faire tourner le moteur manuellement. Au lieu de cela, vous tournez la clé, et la voiture gère le reste en interne.
En code, cela signifie que la classe Car fournit une méthode :start() simple qui délègue le travail réel au moteur :
function Car:start()
print("Turning the key...")
self.engine:run() -- Déléguer à l'objet interne
endLa voiture n'a pas besoin de savoir comment le moteur fonctionne — elle dit simplement au moteur de faire son travail. Cela permet de séparer les responsabilités. La classe Engine gère la logique du moteur, tandis que Car coordonne les éléments :
function Engine:run()
print("Engine running at " .. self.horsepower .. " HP")
end
local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- Sortie :
-- Tourner la clé...
-- Moteur tournant à 250 HPLa délégation crée une interface propre pour les utilisateurs de votre classe. Ils interagissent avec la voiture, pas avec ses pièces internes. Si vous remplacez plus tard l'implémentation du moteur par une autre, l'interface publique de la voiture reste la même — seule la délégation interne change.
Défi
FacileConstruisons un système de lecteur de musique qui démontre la délégation ! Vous allez créer un composant Speaker et un MusicPlayer qui le contient. Le lecteur ne gérera pas directement la sortie sonore ; au lieu de cela, il déléguera cette responsabilité à son haut-parleur interne.
Vous organiserez votre code sur trois fichiers :
Speaker.lua: Créez une classe Speaker avec un constructeur:new(volume)qui stocke le niveau de volume. Incluez une méthode:playSound(trackName)qui affiche :Playing "{trackName}" at volume {volume}MusicPlayer.lua: Créez une classe MusicPlayer dont le constructeur:new(brand, speaker)accepte un nom de marque et un objet Speaker. Le lecteur stocke le haut-parleur à l'intérieur de lui-même. Incluez ces méthodes ::play(trackName)— affiche{brand} player starting...puis délègue à la méthode:playSound()du haut-parleur:stop()— affiche{brand} player stopped
main.lua: Rassemblez le tout ! Lisez les entrées pour le volume du haut-parleur, la marque du lecteur et un nom de piste. Créez d'abord un Speaker, puis passez-le au constructeur du MusicPlayer. Appelez la méthode:play()du lecteur avec le nom de la piste, puis appelez:stop().
Vous recevrez trois entrées :
- Le volume du haut-parleur (un nombre)
- La marque du lecteur de musique (une chaîne de caractères)
- Le nom de la piste à lire (une chaîne de caractères)
Votre sortie devrait montrer le lecteur se coordonnant avec son haut-parleur :
{brand} player starting...
Playing "{trackName}" at volume {volume}
{brand} player stoppedPar exemple, si les entrées sont 75, SoundMax, et Summer Vibes, la sortie devrait être :
SoundMax player starting...
Playing "Summer Vibes" at volume 75
SoundMax player stoppedRemarquez comment le MusicPlayer ne sait pas comment produire du son — il dit simplement à son haut-parleur de s'occuper de cette partie. C'est la délégation en action : l'objet externe fournit une interface propre tandis que le composant interne effectue le travail spécialisé !
Aide-mémoire
La délégation permet à un objet externe de transmettre des appels de méthode à ses composants internes, en gardant les responsabilités séparées et en créant des interfaces propres.
L'objet externe fournit des méthodes simples qui délèguent le travail aux objets internes :
function Car:start()
print("Turning the key...")
self.engine:run() -- Déléguer à l'objet interne
endL'objet interne gère sa propre logique spécialisée :
function Engine:run()
print("Engine running at " .. self.horsepower .. " HP")
end
local engine = Engine:new(250)
local car = Car:new("Coupe", engine)
car:start()
-- Output:
-- Turning the key...
-- Engine running at 250 HPAvantages de la délégation :
- La classe externe n'a pas besoin de savoir comment l'objet interne fonctionne
- Les utilisateurs interagissent avec une interface publique propre
- Les implémentations internes peuvent être remplacées sans modifier l'interface publique
Essayez vous-même
-- main.lua
-- Rassemblez tout !
local Speaker = require('Speaker')
local MusicPlayer = require('MusicPlayer')
-- Lire les entrées
local volume = tonumber(io.read())
local brand = io.read()
local trackName = io.read()
-- TODO : Créer un Speaker avec le volume donné
-- TODO : Créer un MusicPlayer avec la marque et le haut-parleur
-- TODO : Appeler la méthode play du lecteur avec le nom de la piste
-- TODO : Appeler la méthode stop du lecteur
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Object Oriented Programming
1Le concept de « self »
Tables avec fonctions« self » expliciteLa syntaxe avec deux-pointsPoint vs deux-pointsRécapitulatif - Point mobile4Projet : Banque numérique
Configuration du projetMéthode de dépôt7Polymorphisme et Redéfinition
Redéfinition de méthodesAppeler des méthodes parentesDuck TypingInterface communeVérification du typeRécapitulatif - Rôles des employés10Projet : Gestionnaire de formes
Configuration du projetClasse Rectangle2Modèle de prototype de classe
Le concept de prototypeLiaison avec __indexLe constructeur :new()Initialisation des attributsInstances indépendantesRécapitulatif - Usine de voitures5Surcharge d'opérateurs en POO
Additionner des objetsSoustraire des objetsConcaténer des objetsComparer des objets (<, >)Récapitulatif - Calculs de portefeuille8Encapsulation
Conventions de nommageClosures pour la confidentialitéAccès via les ClosuresTables en lecture seuleLogique de validationRécapitulatif - Coffre-fort sécurisé11Patrons de conception (Lite)
Fonctions FactoryTable SingletonPatron IteratorObserver (Écouteur)Récapitulatif - Logger Factory3État et comportement des objets
Variables d'instanceMéthodes GetterMéthodes SetterPropriétés calculéesFormatage de chaînesVérifications d'égalitéRécapitulatif - Note de l'étudiant6Bases de l'héritage
Mise en place de l'héritageHériter des méthodesÉtendre le constructeurAjouter des méthodes enfantsPartagé vs UniqueRécapitulatif - Hiérarchie des formes9Composition et Mixins
Relation 'A un'DélégationMixins simplesAppliquer plusieurs MixinsMixins vs HéritageRécapitulatif - Assemblage de robots