Menu
Coddy logo textTech

Duck Typing

Fa parte della sezione Programmazione orientata agli oggetti del percorso Lua di Coddy. Lezione 39 di 70.

A Lua non interessa la classe di un oggetto. Le importa solo ciò che l'oggetto può fare. Questo concetto si chiama duck typing: «Se cammina come un'anatra e starnazza come un'anatra, è un'anatra». In termini di programmazione, se un oggetto ha il metodo che stai chiamando, funziona.

Ciò significa che classi completamente non correlate possono essere usate insieme, purché condividano lo stesso nome di metodo:

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

Queste classi non hanno alcuna relazione di ereditarietà: sono completamente indipendenti. Eppure possiamo trattarle in modo identico:

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

for _, shape in ipairs(shapes) do
    shape:draw()
end
-- Output:
-- Disegno di un cerchio
-- Disegno di un quadrato
-- Disegno di un cerchio

Il ciclo non controlla di che tipo è ogni oggetto. Chiama semplicemente :draw() e presume che il metodo esista. Questa flessibilità è potente. Puoi aggiungere nuovi tipi di forme senza modificare affatto il codice del ciclo. Finché la nuova classe implementa :draw(), funziona e basta.

challenge icon

Sfida

Facile

Dimostriamo la potenza del duck typing creando un sistema di notifiche con classi completamente indipendenti, che possono essere elaborate tutte allo stesso modo!

Creerai tre classi di notifiche indipendenti, nessuna delle quali eredita dalle altre, ma tutte implementano un metodo :send(). Questo significa che puoi scorrere una raccolta mista e chiamare :send() su ciascun elemento senza preoccuparti del suo tipo effettivo.

Organizzerai il codice in quattro file:

  • Email.lua: una classe con un costruttore :new(recipient) che memorizza il destinatario dell'email. Il suo metodo :send() dovrebbe stampare Emailing {recipient}.
  • SMS.lua: una classe completamente separata con un costruttore :new(phoneNumber). Il suo metodo :send() dovrebbe stampare Texting {phoneNumber}.
  • PushNotification.lua: un'altra classe indipendente con un costruttore :new(deviceId). Il suo metodo :send() dovrebbe stampare Pushing to {deviceId}.
  • main.lua: metti insieme ogni elemento! Leggi tre input, crea un'istanza di ogni tipo di notifica, inseriscile tutte in un'unica tabella, quindi scorri la tabella e chiama :send() su ciascuna.

Riceverai tre input:

  1. Un destinatario email (ad es., alice@example.com)
  2. Un numero di telefono (ad es., 555-1234)
  3. L'ID di un dispositivo (ad es., device_99)

Nel file principale, crea tutti e tre gli oggetti di notifica, memorizzali in una tabella e scorri la tabella chiamando :send() su ciascuno. L'ordine dovrebbe essere: prima Email, poi SMS, infine PushNotification.

Ad esempio, se gli input sono bob@mail.com, 555-9876 e phone_42, l'output dovrebbe essere:

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

Nota che il ciclo non deve verificare il tipo di ciascun oggetto. Si fida semplicemente del fatto che ogni oggetto nella raccolta abbia un metodo :send(). Questo è il duck typing in azione! Se può eseguire :send(), è una notifica.

Provalo tu

-- main.lua
-- Riunisci tutti i tipi di notifica e dimostra il duck typing

-- Importa le classi delle notifiche
local Email = require('Email')
local SMS = require('SMS')
local PushNotification = require('PushNotification')

-- Leggi gli input
local recipient = io.read()
local phoneNumber = io.read()
local deviceId = io.read()

-- TODO: Crea un'istanza di ogni tipo di notifica

-- TODO: Inserisci tutte le notifiche in un'unica tabella (prima Email, poi SMS, infine PushNotification)

-- TODO: Scorri la tabella e chiama :send() su ogni notifica
-- Questo dimostra il duck typing: non controlliamo il tipo, chiamiamo semplicemente :send()
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Lua online