In questa serie di articoli (in 4 parti) verrà presentato un argomento che sono sicuro molti hanno sfiorato nelle loro scorribande da programmatori, ma non hanno mai usato o approfondito. E’ di fatto un argomento abbastanza complesso (giusto per farvi capire COM e ACTIVEX si basano esclusivamente sulle interfacce) e materiale che descrive l’argomento in maniera chiara è difficile da trovare. Però ci proviamo a descriverlo, se non altro penso possa servire come cultura e per comprendere magari parti di codice che contengono tali definizioni.
Le interfacce, da non confondere con la sezione di una unità pascal o con la definizione di grafica (interfacce grafiche), sono “scheletri” di definizioni che possono poi essere usate dalle classi per implementarne i metodi descritti.
Esempio di definizione di una interfaccia:
type
// Definizione di una interfaccia, normalmente inizia con la I maiuscola
IRecyclable = Interface (IInterface)
// qui viene definita una sola funzione, ma ce ne possono essere quante se ne vogliono
function materialIsRecyclable : Boolean;
// questa proprietà serve a richiamare la funzione, ma non è obbligatorio usarla
// in questo esempio diciamo che probabilmente prevediamo di rendere pubblica la
// proprietà e privata la funzione quando verranno definite nella classe
property isRecyclable : Boolean read materialIsRecyclable ;
end;
Nelle interfacce si possono definire solo getter / setter e metodi (ossia proprietà, procedure e funzioni), non possono essere definite variabili, campi o altro di alcun tipo e non vengono definite le implementazioni. Tutto è pubblico e non esiste il “private”, il “protected” o il “published”. Tutto ciò dovrà essere implementato IN OGNI SINGOLA CLASSE che deriva direttamente l’interfaccia. Da ciò dovreste avere compreso che non è possibile istanziare direttamente una interfaccia, deve per forza essere implementata all’interno di una classe e da qui riusciremo ad “usarla”.
In pratica le interfacce definiscono cosa una classe (o meglio tutte le classi che deriveranno dalla interfaccia) DEVE implementare ed esporre. Ciò non significa che la classe può esporre solo ciò che l’interfaccia definisce, anzi per forza di cose deve dichiarare e definire variabili da usare internamente, oltre a tutto ciò che già conosciamo (proprietà, metodi, procedure, funzioni, etc …).
L’interfaccia è di fatto la separazione “perfetta” tra la definizione e l’implementazione. Non è a caso che le due sezioni principali di una unit pascal si chiamano “interface” e “implementation”, anche se ciò non ha a che vedere con le “interface” di cui stiamo discutendo.
Qui potete leggere qualcosa sull’argomento (è in inglese): https://wiki.freepascal.org/Understanding_Interfaces
Le interfacce godono di ciò che si chiama “reference counting” e vengono automaticamente distrutte quando il “reference counting” và a zero, nel seguito (prossimo post) vedremo un esempio di ciò.
Per ora direi che è sufficiente, spero di avere suscitato un pò di curiosità, alla prossima (parte 2) (qui il link https://blog.lazaruspascal.it/2023/09/25/interfacce-interface-parte-2/)