Menu
Coddy logo textTech

Duck Typing

Fait partie de la section Programmation orientée objet du Journey Lua de Coddy. Leçon 39 sur 70.

Lua ne se soucie pas de la classe d’un objet. Elle se soucie uniquement de ce que l’objet peut faire. Ce concept s’appelle le typage canard : « S’il marche comme un canard et qu’il cancane comme un canard, c’est un canard. » En termes de programmation, si un objet possède la méthode que vous appelez, cela fonctionne.

Cela signifie que des classes complètement indépendantes peuvent être utilisées ensemble, tant qu’elles partagent le même nom de méthode :

local Circle = {}
Circle.__index = Circle
function Circle:new() 
    local obj = {}
    setmetatable(obj, Circle)
    return obj
end
function Circle:draw()
    print("Drawing a circle")
end

local Square = {}
Square.__index = Square
function Square:new()
    local obj = {}
    setmetatable(obj, Square)
    return obj
end
function Square:draw()
    print("Drawing a square")
end

Ces classes n’ont aucune relation d’héritage : elles sont complètement indépendantes. Pourtant, nous pouvons les traiter de manière identique :

local shapes = {Circle:new(), Square:new(), Circle:new()}

for _, shape in ipairs(shapes) do
    shape:draw()
end
-- Sortie :
-- Dessin d'un cercle
-- Dessin d'un carré
-- Dessin d'un cercle

La boucle ne vérifie pas le type de chaque objet. Elle appelle simplement :draw() et fait confiance à l’existence de la méthode. Cette flexibilité est puissante. Vous pouvez ajouter de nouveaux types de formes sans modifier le code de la boucle. Tant que la nouvelle classe implémente :draw(), cela fonctionne immédiatement.

challenge icon

Défi

Facile

Démontrons la puissance du duck typing en construisant un système de notifications avec des classes totalement indépendantes qui peuvent toutes être traitées de la même manière !

Tu vas créer trois classes de notification indépendantes, dont aucune n'hérite des autres, mais qui implémentent toutes une méthode :send(). Cela signifie que tu peux parcourir une collection mixte et appeler :send() sur chacune d'elles sans te soucier de son type réel.

Tu organiseras ton code sur quatre fichiers :

  • Email.lua : une classe avec un constructeur :new(recipient) qui enregistre le destinataire de l'e-mail. Sa méthode :send() doit afficher Emailing {recipient}.
  • SMS.lua : une classe complètement distincte avec un constructeur :new(phoneNumber). Sa méthode :send() doit afficher Texting {phoneNumber}.
  • PushNotification.lua : une autre classe indépendante avec un constructeur :new(deviceId). Sa méthode :send() doit afficher Pushing to {deviceId}.
  • main.lua : rassemble tout ! Lis trois entrées, crée une instance de chaque type de notification, place-les toutes dans une seule table, puis parcours cette table et appelle :send() sur chacune.

Tu recevras trois entrées :

  1. Un destinataire d'e-mail (par exemple, alice@example.com)
  2. Un numéro de téléphone (par exemple, 555-1234)
  3. Un identifiant d'appareil (par exemple, device_99)

Dans ton fichier principal, crée les trois objets de notification, stocke-les dans une table et parcours cette table en appelant :send() sur chacun. L'ordre doit être le suivant : Email en premier, puis SMS, puis PushNotification.

Par exemple, si les entrées sont bob@mail.com, 555-9876 et phone_42, la sortie doit être :

Emailing bob@mail.com
Texting 555-9876
Pushing to phone_42

Remarque que ta boucle n'a pas besoin de vérifier le type de chaque objet. Elle fait simplement confiance au fait que chaque objet de la collection possède une méthode :send(). C'est le duck typing en action ! S'il peut exécuter :send(), c'est une notification.

Essayez vous-même

-- main.lua
-- Rassembler tous les types de notification et démontrer le duck typing

-- Importer les classes de notification
local Email = require('Email')
local SMS = require('SMS')
local PushNotification = require('PushNotification')

-- Lire les entrées
local recipient = io.read()
local phoneNumber = io.read()
local deviceId = io.read()

-- TODO: Créer une instance de chaque type de notification

-- TODO: Mettre toutes les notifications dans une seule table (Email en premier, puis SMS, puis PushNotification)

-- TODO: Parcourir la table et appeler :send() sur chaque notification
-- Ceci démontre le duck typing - nous ne vérifions pas le type, nous appelons simplement :send()
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 Programmation orientée objet

Entraînez-vous par vous-même : Compilateur Lua en ligne