Interface commune
Fait partie de la section Programmation orientée objet du Journey Lua de Coddy. Leçon 40 sur 70.
Le typage canard nous a montré que des classes sans lien peuvent fonctionner ensemble si elles partagent les mêmes noms de méthodes. Cette idée mène à un concept de conception puissant : l’interface commune. Lorsque vous concevez intentionnellement plusieurs classes pour qu’elles aient les mêmes signatures de méthodes, vous créez des composants interchangeables.
Imaginez que vous construisiez un système de journalisation. Vous pourriez vouloir envoyer des messages vers différentes destinations : un fichier, l’écran ou même un réseau. Au lieu d’écrire du code distinct pour chacune, vous concevez toutes vos classes de sortie afin qu’elles implémentent la même méthode :write() :
local LogFile = {}
LogFile.__index = LogFile
function LogFile:new(filename)
local obj = {filename = filename}
setmetatable(obj, LogFile)
return obj
end
function LogFile:write(message)
print("[FILE:" .. self.filename .. "] " .. message)
end
local Screen = {}
Screen.__index = Screen
function Screen:new()
local obj = {}
setmetatable(obj, Screen)
return obj
end
function Screen:write(message)
print("[SCREEN] " .. message)
endDésormais, tout code qui doit afficher des messages peut accepter l’un ou l’autre type :
local function logMessage(output, msg)
output:write(msg)
end
local file = LogFile:new("app.log")
local screen = Screen:new()
logMessage(file, "Starting up") -- [FILE:app.log] Démarrage
logMessage(screen, "Starting up") -- [SCREEN] DémarrageLa fonction logMessage ne sait pas, et n’a pas besoin de savoir, quelle classe elle reçoit. Elle attend seulement une méthode :write(). Cela rend votre code flexible. Vous pouvez ajouter ultérieurement de nouveaux types de sortie sans modifier les fonctions existantes.
Défi
FacileConstruisons un système de traitement des paiements où différents modes de paiement peuvent être utilisés de manière interchangeable ! Vous allez créer deux classes de paiement complètement indépendantes qui partagent une interface commune, une méthode :process(amount), permettant à tout code qui gère les paiements de fonctionner avec l’un ou l’autre type sans connaître la différence.
Vous allez organiser votre code sur trois fichiers :
CreditCard.lua: uneclassde paiement avec un constructeur:new(cardNumber)qui stocke le numéro de carte. Sa méthode:process(amount)doit afficherCharging {amount} to card {cardNumber}.BankTransfer.lua: uneclassde paiement complètement distincte avec un constructeur:new(accountId). Sa méthode:process(amount)doit afficherTransferring {amount} from account {accountId}.main.lua: créez unefunctionappeléehandlePayment(paymentMethod, amount)qui accepte toutobjectde paiement et un montant, puis appelle:process(amount)sur celui-ci. Cettefunctionn’a pas besoin de savoir si elle traite une carte de crédit ou un virement bancaire. Elle s’attend simplement à ce que l’objectpossède une méthode:process().
Vous recevrez trois entrées :
- Un numéro de carte de crédit (par exemple,
4532-1234-5678) - Un identifiant de compte bancaire (par exemple,
ACC-9876) - Un montant de paiement (par exemple,
150)
Dans votre fichier principal, créez une instance de chaque type de paiement à l’aide des deux premières entrées. Utilisez ensuite votre handlePayment pour traiter le montant indiqué avec les deux modes de paiement : d’abord la carte de crédit, puis le virement bancaire.
Par exemple, si les entrées sont 1111-2222-3333, ACC-5555 et 75, la sortie doit être :
Charging 75 to card 1111-2222-3333
Transferring 75 from account ACC-5555La beauté de cette conception est que votre handlePayment fonctionne avec tout object qui implémente :process(). Vous pourriez ajouter une class PayPal demain et, tant qu’elle possède une méthode :process(amount), elle fonctionnerait avec votre function existante sans aucune modification !
Essayez vous-même
-- Importer les classes de paiement
local CreditCard = require('CreditCard')
local BankTransfer = require('BankTransfer')
-- Lire les entrées
local cardNumber = io.read()
local accountId = io.read()
local amount = tonumber(io.read())
-- TODO: Créer la fonction handlePayment qui accepte n'importe quel objet de paiement
-- et un montant, puis appelle :process(amount) sur celui-ci
-- TODO: Créer des instances de CreditCard et BankTransfer en utilisant les entrées
-- TODO: Utiliser handlePayment pour traiter le montant via les deux méthodes de paiement
-- D'abord la carte de crédit, puis le virement bancaire
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
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 RectangleClasse CercleMéthode PérimètreCollection de formesAire totaleFiltrer les formes2Modè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 formesEntraînez-vous par vous-même : Compilateur Lua en ligne