Menu
Coddy logo textTech

Relation 'A un'

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

Tout au long de ce cours, vous avez utilisé l'héritage pour partager des comportements entre les classes — un Dog "est un" Animal. Mais l'héritage n'est pas toujours le bon outil.

Parfois, les objets ne partagent pas d'arbre généalogique ; au lieu de cela, un objet en contient simplement un autre. C'est ce qu'on appelle la composition, et cela modélise une relation « a un » (has-a).

Considérez une voiture. Une voiture n'est pas un type de moteur — elle a un moteur. Le moteur est un objet distinct qui existe à l'intérieur de la voiture :

local Engine = {}
Engine.__index = Engine

function Engine:new(horsepower)
    local obj = {horsepower = horsepower}
    setmetatable(obj, Engine)
    return obj
end

local Car = {}
Car.__index = Car

function Car:new(model, engine)
    local obj = {
        model = model,
        engine = engine  -- Stocker l'objet Engine à l'intérieur de Car
    }
    setmetatable(obj, Car)
    return obj
end

Lors de la création d'une voiture, vous passez un objet moteur existant à son constructeur :

local myEngine = Engine:new(200)
local myCar = Car:new("Sedan", myEngine)

print(myCar.engine.horsepower)  -- 200

La voiture n'hérite pas du moteur — elle détient simplement une référence vers celui-ci. Cela permet de garder les deux classes indépendantes. Vous pourriez remplacer le moteur par un autre, ou utiliser la même classe de moteur dans une moto.

La composition vous offre une flexibilité que l'héritage ne peut pas : vous assemblez des objets à partir de composants plutôt que de les enfermer dans une hiérarchie familiale rigide.

challenge icon

Défi

Facile

Construisons un système informatique en utilisant la composition ! Au lieu de l'héritage, vous allez créer un Computer qui possède un CPU à l'intérieur—démontrant ainsi la relation "has-a" (a un).

Vous organiserez votre code sur trois fichiers :

  • CPU.lua : Créez une classe CPU avec un constructeur :new(brand, speed) qui stocke le nom de la marque et la vitesse en GHz. Incluez une méthode :getInfo() qui retourne une chaîne de caractères au format : {brand} @ {speed}GHz
  • Computer.lua : Créez une classe Computer dont le constructeur :new(model, cpu) accepte un nom de modèle et un objet CPU. Le Computer stocke l'objet CPU en son sein (composition !). Incluez une méthode :describe() qui affiche le modèle de l'ordinateur et les informations de son CPU.
  • main.lua : Rassemblez le tout ! Lisez les entrées pour la marque du CPU, la vitesse du CPU et le modèle de l'ordinateur. Créez d'abord un objet CPU, puis passez-le au constructeur du Computer. Enfin, appelez la méthode :describe() de l'ordinateur.

Vous recevrez trois entrées :

  1. La marque du CPU (une chaîne de caractères)
  2. La vitesse du CPU en GHz (un nombre)
  3. Le nom du modèle de l'ordinateur (une chaîne de caractères)

Votre sortie doit afficher la description de l'ordinateur, qui inclut les informations de son CPU contenu :

Model: {model}
CPU: {brand} @ {speed}GHz

Par exemple, si les entrées sont Intel, 3.5, et WorkStation, la sortie doit être :

Model: WorkStation
CPU: Intel @ 3.5GHz

Remarquez comment le Computer n'hérite pas de CPU—il détient simplement une référence vers celui-ci. La méthode :describe() du Computer accède aux données du CPU via l'objet stocké, montrant comment la composition vous permet de construire des objets complexes à partir de parties plus simples !

Aide-mémoire

Les objets peuvent être liés par la composition, qui modélise une relation de type « a un » (has-a). Au lieu de l'héritage, un objet en contient un autre en tant que composant.

Exemple de composition avec une voiture qui possède un moteur :

local Engine = {}
Engine.__index = Engine

function Engine:new(horsepower)
    local obj = {horsepower = horsepower}
    setmetatable(obj, Engine)
    return obj
end

local Car = {}
Car.__index = Car

function Car:new(model, engine)
    local obj = {
        model = model,
        engine = engine  -- Stocke l'objet Engine à l'intérieur de Car
    }
    setmetatable(obj, Car)
    return obj
end

Création et utilisation d'objets composés :

local myEngine = Engine:new(200)
local myCar = Car:new("Sedan", myEngine)

print(myCar.engine.horsepower)  -- 200

La composition offre de la flexibilité en assemblant des objets à partir de pièces plutôt qu'en utilisant des hiérarchies d'héritage rigides. Les composants restent indépendants et peuvent être réutilisés dans différentes classes.

Essayez vous-même

-- main.lua
-- Rassembler tout en utilisant la composition

local CPU = require('CPU')
local Computer = require('Computer')

-- Lire les entrées
local cpuBrand = io.read()
local cpuSpeed = tonumber(io.read())
local computerModel = io.read()

-- TODO: Créer un objet CPU avec la marque et la vitesse

-- TODO: Créer un objet Computer avec le modèle et l'objet CPU

-- TODO: Appeler la méthode describe() de l'ordinateur pour afficher le résultat
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