Menu
Coddy logo textTech

Appliquer plusieurs Mixins

Fait partie de la section Object Oriented Programming du Journey Lua de Coddy — leçon 52 sur 70.

Un seul mixin ajoute un ensemble de comportements à une classe. Mais les objets réels ont souvent besoin de capacités provenant de sources multiples. Un objet de jeu peut avoir besoin de se déplacer et d'être visible à l'écran — deux préoccupations distinctes qui n'ont pas leur place dans le même mixin.

La solution est simple : appliquez plusieurs mixins à la même classe. Chaque mixin apporte ses propres méthodes, et la classe finit par toutes les posséder :

local Movable = {}
function Movable:move(dx, dy)
    self.x = self.x + dx
    self.y = self.y + dy
end

local Visible = {}
function Visible:show()
    print("Showing at " .. self.x .. ", " .. self.y)
end
function Visible:hide()
    print("Hidden")
end

Appliquez les deux mixins à votre classe en utilisant la même fonction utilitaire que précédemment :

local function applyMixin(class, mixin)
    for key, value in pairs(mixin) do
        class[key] = value
    end
end

local GameObject = {}
GameObject.__index = GameObject

applyMixin(GameObject, Movable)
applyMixin(GameObject, Visible)

Désormais, les instances de GameObject peuvent à la fois se déplacer et s'afficher :

local obj = setmetatable({x = 0, y = 0}, GameObject)
obj:move(5, 3)
obj:show()  -- Affichage à 5, 3

Une mise en garde : si deux mixins définissent le même nom de méthode, le second appliqué écrasera le premier. Gardez vos méthodes de mixin distinctes pour éviter tout comportement inattendu.

challenge icon

Défi

Facile

Construisons une classe Character pour un jeu qui combine plusieurs capacités en utilisant des mixins ! Votre personnage sera capable à la fois d'attaquer des ennemis et de se soigner lui-même — deux comportements distincts provenant de mixins séparés.

Vous organiserez votre code sur quatre fichiers :

  • Attacker.lua : Créez un mixin avec une méthode :attack(targetName) qui affiche {self.name} attacks {targetName} for {self.damage} damage! (suppose que l'objet possède les champs name et damage)
  • Healer.lua : Créez un mixin avec une méthode :heal(amount) qui ajoute le montant à self.health et affiche {self.name} heals for {amount}. Health: {newHealth}
  • Character.lua : Créez une classe Character avec un constructeur :new(name, health, damage) qui stocke les trois attributs. Appliquez les mixins Attacker et Healer pour que chaque personnage puisse attaquer et soigner. Incluez une méthode :status() qui affiche {name} - Health: {health}, Damage: {damage}
  • main.lua : Écrivez la fonction utilitaire applyMixin ici. Lisez les entrées pour le nom d'un personnage, sa santé, ses dégâts, une cible à attaquer et un montant de soin. Créez un Character, affichez son statut, faites-lui attaquer la cible, soignez-le, puis affichez à nouveau son statut.

Vous recevrez cinq entrées :

  1. Nom du personnage (une chaîne de caractères)
  2. Santé de départ (un nombre)
  3. Valeur des dégâts (un nombre)
  4. Nom de la cible à attaquer (une chaîne de caractères)
  5. Montant à soigner (un nombre)

Votre sortie devrait montrer le personnage utilisant les deux capacités des mixins :

{name} - Health: {health}, Damage: {damage}
{name} attacks {target} for {damage} damage!
{name} heals for {healAmount}. Health: {newHealth}
{name} - Health: {newHealth}, Damage: {damage}

Par exemple, si les entrées sont Warrior, 100, 25, Goblin, et 30, la sortie devrait être :

Warrior - Health: 100, Damage: 25
Warrior attacks Goblin for 25 damage!
Warrior heals for 30. Health: 130
Warrior - Health: 130, Damage: 25

Chaque mixin apporte sa propre méthode à la classe Character. Le personnage n'hérite d'aucun des mixins — il acquiert simplement leurs capacités via la fonction applyMixin. C'est toute la puissance de la combinaison de plusieurs mixins !

Aide-mémoire

Plusieurs mixins peuvent être appliqués à une seule classe pour combiner différents ensembles de comportements. Chaque mixin apporte ses propres méthodes à la classe.

Définissez des mixins distincts pour différentes préoccupations :

local Movable = {}
function Movable:move(dx, dy)
    self.x = self.x + dx
    self.y = self.y + dy
end

local Visible = {}
function Visible:show()
    print("Showing at " .. self.x .. ", " .. self.y)
end
function Visible:hide()
    print("Hidden")
end

Appliquez plusieurs mixins à une classe en utilisant la fonction utilitaire applyMixin :

local function applyMixin(class, mixin)
    for key, value in pairs(mixin) do
        class[key] = value
    end
end

local GameObject = {}
GameObject.__index = GameObject

applyMixin(GameObject, Movable)
applyMixin(GameObject, Visible)

La classe possède désormais les méthodes de tous les mixins appliqués :

local obj = setmetatable({x = 0, y = 0}, GameObject)
obj:move(5, 3)
obj:show()  -- Showing at 5, 3

Important : Si deux mixins définissent le même nom de méthode, le deuxième mixin appliqué écrasera le premier. Gardez les noms de méthodes distincts entre les mixins pour éviter les conflits.

Essayez vous-même

-- Fichier principal

-- TODO: Écrire la fonction auxiliaire applyMixin
-- Cette fonction doit copier toutes les méthodes d'une table mixin vers une table cible
local function applyMixin(target, mixin)
    -- TODO: Implémenter l'application du mixin
end

-- Rendre applyMixin disponible globalement pour que Character.lua puisse l'utiliser
_G.applyMixin = applyMixin

local Character = require('Character')

-- Lire les entrées
local name = io.read()
local health = tonumber(io.read())
local damage = tonumber(io.read())
local targetName = io.read()
local healAmount = tonumber(io.read())

-- TODO: Créer un Personnage avec le nom, la santé et les dégâts donnés

-- TODO: Afficher le statut du personnage

-- TODO: Faire en sorte que le personnage attaque la cible

-- TODO: Faire en sorte que le personnage se soigne lui-même

-- TODO: Afficher à nouveau le statut du personnage
quiz iconTestez-vous

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