Mixins simples
Fait partie de la section Object Oriented Programming du Journey Lua de Coddy — leçon 51 sur 70.
La composition vous permet de placer des objets à l'intérieur d'autres objets. Mais que se passe-t-il si vous voulez partager un comportement entre des classes non liées ?
Un Player et un MenuItem pourraient tous deux avoir besoin d'une méthode :describe(), mais ils ne partagent pas de classe parente. C'est là que les mixins interviennent.
Un mixin est simplement une table contenant des fonctions. Vous « mixez » ces fonctions dans une classe en les copiant :
local Printable = {}
function Printable:describe()
print("Object: " .. tostring(self))
end
function Printable:log(message)
print("[LOG] " .. message)
endPour appliquer ce mixin à une classe, vous copiez chaque fonction de la table du mixin dans la table de la classe :
local function applyMixin(class, mixin)
for key, value in pairs(mixin) do
class[key] = value
end
end
local Player = {}
Player.__index = Player
applyMixin(Player, Printable) -- Maintenant, Player possède :describe() et :log()Après avoir appliqué le mixin, toute instance de Player peut appeler ces méthodes comme si elles étaient définies directement sur la classe :
local p = setmetatable({}, Player)
p:log("Player created") -- [LOG] Joueur crééContrairement à l'héritage, les mixins ne créent pas de relation parent-enfant. Vous copiez simplement des fonctions d'une table à une autre.
Cela rend les mixins parfaits pour partager des comportements utilitaires — comme la journalisation, la sérialisation ou les méthodes de description — entre des classes qui n'ont par ailleurs rien en commun.
Défi
FacileConstruisons un système de marquage (tagging) en utilisant des mixins ! Vous allez créer un mixin Taggable qui peut être appliqué à n'importe quelle classe, donnant aux objets la capacité de gérer une collection de tags—utile pour catégoriser des articles, des publications ou toute entité nécessitant des étiquettes.
Vous organiserez votre code sur trois fichiers :
Taggable.lua: Créez une table mixin contenant deux méthodes ::addTag(tag)— ajoute un tag àself.tags(suppose que la table existe):listTags()— affiche tous les tags au formatTags: tag1, tag2, tag3(ouTags: nonesi elle est vide)
Article.lua: Créez une classe Article avec un constructeur:new(title)qui stocke le titre et initialise une tabletagsvide. Appliquez le mixin Taggable pour donner aux instances d'Article des capacités de marquage. Incluez une méthode:getTitle()qui retourne le titre de l'article.main.lua: Écrivez la fonction utilitaireapplyMixinici (vous l'utiliserez dans Article.lua via require). Ensuite, lisez les entrées pour un titre d'article et deux tags. Créez un Article, ajoutez-lui les deux tags, affichez le titre et listez tous les tags.
Vous recevrez trois entrées :
- Le titre de l'article (une chaîne de caractères)
- Le premier tag à ajouter (une chaîne de caractères)
- Le deuxième tag à ajouter (une chaîne de caractères)
Votre sortie doit afficher le titre de l'article suivi de ses tags :
Title: {title}
Tags: {tag1}, {tag2}Par exemple, si les entrées sont Lua Basics, programming, et tutorial, la sortie doit être :
Title: Lua Basics
Tags: programming, tutorialRappel : les méthodes du mixin fonctionnent parce que les instances d'Article possèdent une table tags sur laquelle les méthodes du mixin peuvent opérer. Le mixin ne crée pas cette table—c'est votre constructeur Article qui le fait. Le mixin fournit simplement le comportement partagé !
Aide-mémoire
Un mixin est une table contenant des fonctions qui peuvent être partagées entre des classes non liées sans créer de relation parent-enfant.
Pour créer un mixin, définissez une table avec des méthodes :
local Printable = {}
function Printable:describe()
print("Object: " .. tostring(self))
end
function Printable:log(message)
print("[LOG] " .. message)
endPour appliquer un mixin à une classe, copiez ses fonctions dans la table de la classe :
local function applyMixin(class, mixin)
for key, value in pairs(mixin) do
class[key] = value
end
end
local Player = {}
Player.__index = Player
applyMixin(Player, Printable)Après avoir appliqué le mixin, les instances peuvent appeler les méthodes du mixin :
local p = setmetatable({}, Player)
p:log("Player created") -- [LOG] Player createdLes mixins sont idéaux pour partager des comportements utilitaires tels que la journalisation, la sérialisation ou le marquage entre des classes qui ne partagent pas d'héritage.
Essayez vous-même
-- Fichier principal pour le système de marquage
local Taggable = require('Taggable')
local Article = require('Article')
-- TODO : Implémenter la fonction applyMixin
-- Cette fonction doit copier toutes les méthodes d'une table mixin vers une table cible
function applyMixin(target, mixin)
-- TODO : Parcourir le mixin et copier chaque méthode vers la cible
end
-- Lire les entrées
local title = io.read()
local tag1 = io.read()
local tag2 = io.read()
-- TODO : Créer un Article avec le titre donné
-- TODO : Ajouter les deux tags à l'article
-- TODO : Afficher le titre au format : Title: {title}
-- TODO : Lister tous les tags en utilisant la méthode listTags
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