Partagé vs Unique
Fait partie de la section Object Oriented Programming du Journey Lua de Coddy — leçon 35 sur 70.
Lorsqu'on travaille avec l'héritage, il est important de comprendre où réside chaque donnée. Certains attributs sont partagés — définis dans le parent et accessibles à tous les enfants. D'autres sont uniques — créés spécifiquement dans la classe enfant ou l'instance.
Considérez cette hiérarchie :
local Animal = {}
Animal.__index = Animal
Animal.kingdom = "Animalia" -- Partagé : défini sur la classe
function Animal:new(name)
local obj = {name = name} -- Unique : stocké sur chaque instance
setmetatable(obj, Animal)
return obj
endlocal Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
Dog.sound = "bark" -- Partagé par tous les chiens
function Dog:new(name, breed)
local obj = Animal.new(Animal, name)
obj.breed = breed -- Unique : chaque chien a sa propre race
setmetatable(obj, Dog)
return obj
endLorsque vous créez une instance de Dog, certaines valeurs existent directement sur l'objet, tandis que d'autres sont trouvées via la chaîne de recherche (lookup chain) :
local rex = Dog:new("Rex", "German Shepherd")
-- Unique à cette instance (stocké sur rex)
print(rex.name) -- "Rex"
print(rex.breed) -- "German Shepherd"-- Partagé (trouvé via recherche)
print(rex.sound) -- "bark" (de Dog)
print(rex.kingdom) -- "Animalia" (de Animal)La distinction clé : les champs assignés à obj dans les constructeurs sont uniques à chaque instance, tandis que les champs définis directement sur les tables de classe sont partagés entre toutes les instances de cette classe et de ses enfants.
Défi
FacileExplorons comment les données circulent à travers une hiérarchie d'héritage en construisant un système de classes Creature et Dragon. Vous verrez par vous-même quels attributs sont partagés entre toutes les instances et lesquels sont uniques à chaque objet individuel.
Vous organiserez votre code sur trois fichiers :
Creature.lua: Définissez votre classe parente avec un attribut de niveau classe partagéworld = "Fantasy Realm"que toutes les créatures partagent. Incluez un constructeur:new(name)qui stocke le nom de la créature en tant qu'attribut d'instance.Dragon.lua: Définissez votre classe enfant qui hérite de Creature. Ajoutez un attribut de niveau classe partagéelement = "fire"que tous les dragons partagent. Votre constructeur:new(name, color)doit appeler le constructeur parent pour le nom, puis ajoutercolorcomme attribut d'instance unique pour chaque dragon.main.lua: Créez deux dragons différents et inspectez leurs attributs pour démontrer la différence entre les données partagées et uniques.
Vous recevrez deux entrées :
- Le nom et la couleur du premier dragon, séparés par une virgule (par exemple,
Smaug,red) - Le nom et la couleur du deuxième dragon, séparés par une virgule (par exemple,
Draco,gold)
Dans votre fichier principal, créez les deux dragons avec leurs noms et couleurs respectifs. Ensuite, affichez les informations suivantes dans cet ordre exact :
- Le
namedu premier dragon - La
colordu premier dragon - Le
namedu deuxième dragon - La
colordu deuxième dragon - L'
elementdu premier dragon (partagé depuis la classe Dragon) - L'
elementdu deuxième dragon (partagé depuis la classe Dragon) - Le
worlddu premier dragon (partagé depuis la classe Creature)
Par exemple, si les entrées sont Smaug,red et Draco,gold, la sortie devrait être :
Smaug
red
Draco
gold
fire
fire
Fantasy RealmRemarquez comment name et color sont différents pour chaque dragon (attributs d'instance uniques), tandis que element et world sont les mêmes pour les deux (attributs de classe partagés trouvés via la chaîne de recherche).
Aide-mémoire
Dans les hiérarchies d'héritage, les attributs peuvent être soit partagés (définis sur la table de classe), soit uniques (stockés sur les instances individuelles).
Les attributs partagés sont définis directement sur les tables de classe et sont accessibles via la chaîne de recherche de la métatable :
local Animal = {}
Animal.__index = Animal
Animal.kingdom = "Animalia" -- Partagé par tous les AnimalsLes attributs uniques sont assignés à l'objet d'instance (obj) dans les constructeurs :
function Animal:new(name)
local obj = {name = name} -- Unique à chaque instance
setmetatable(obj, Animal)
return obj
endLes classes filles peuvent avoir leurs propres attributs partagés tout en héritant des attributs parents :
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
Dog.sound = "bark" -- Partagé par tous les Dogs
function Dog:new(name, breed)
local obj = Animal.new(Animal, name) -- Appeler le constructeur parent
obj.breed = breed -- Ajouter un attribut unique à la classe fille
setmetatable(obj, Dog)
return obj
endAccès aux attributs :
local rex = Dog:new("Rex", "German Shepherd")
-- Unique (stocké directement sur rex)
print(rex.name) -- "Rex"
print(rex.breed) -- "German Shepherd"
-- Partagé (trouvé via la recherche de métatable)
print(rex.sound) -- "bark" (de la classe Dog)
print(rex.kingdom) -- "Animalia" (de la classe Animal)Essayez vous-même
-- main.lua: Créer des dragons et démontrer les attributs partagés vs uniques
local Dragon = require('Dragon')
-- Lire l'entrée pour le premier dragon (nom,couleur)
local input1 = io.read()
-- Lire l'entrée pour le deuxième dragon (nom,couleur)
local input2 = io.read()
-- TODO: Analyser la première entrée pour extraire le nom et la couleur
-- Astuce: Utiliser string.match avec le motif "([^,]+),([^,]+)"
-- TODO: Analyser la deuxième entrée pour extraire le nom et la couleur
-- TODO: Créer le premier dragon avec son nom et sa couleur
-- TODO: Créer le deuxième dragon avec son nom et sa couleur
-- TODO: Imprimer les éléments suivants dans l'ordre :
-- 1. Nom du premier dragon
-- 2. Couleur du premier dragon
-- 3. Nom du deuxième dragon
-- 4. Couleur du deuxième dragon
-- 5. Élément du premier dragon (partagé de la classe Dragon)
-- 6. Élément du deuxième dragon (partagé de la classe Dragon)
-- 7. Monde du premier dragon (partagé de la classe Creature)
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 formes