Capita piuttosto spesso che classi diverse abbiano in realtà funzionalità comuni e che però non si possa far sì che queste siano sottoclassi di una classe comune; altre volte la creazione di una classe comune non è neanche desiderabile. Proviamo a vedere un esempio.
Vogliamo realizzare un programma che gestisca delle squadre di atletica, tra le cose che deve fare c'è la gestione di una rubrica telefonica che mi permetta di visualizzare i numeri di telefono di diversi soggetti con cui la mia società sportiva ha contatto: gli Atleti e le Squadre.
Di una Squadra
mi interessa memorizzare il colore della maglia, il nome e il numero di telefono; di un Atleta
mi interessa
memorizzare il numero di telefono, il nome e il tempo migliore sui 100m.
Il mio programma ha anche una classe che permette di visualizzare i numeri di telefono che si chiama VisualizzatoreRubrica
e per adesso
questa classe ha due soli metodi pubblici:
class VisualizzatoreRubrica { /* altri metodi e proprietà */ public void visualizzaSquadra(Squadra s){ campoNome.setText(s.getNome()); ... } public void visualizzaAtleta(Atleta a){ campoNome.setText(a.getNome()); ... } }
E se in futuro venissero create altre entità (ad esempio "Allenatore" o "Palestra") che io vorrò visualizzare? Dovrei di nuovo andare a modificare
VisualizzatoreRubrica
. Questa cosa è tutt'altro che comoda perché ad esempio ad occuparsi di tale interfaccia grafica potrebbe essere un
programmatore mentre a gestire le classi Squadra, Atleta, Allenatore e simili è un altro programmatore o sono addirittura più di uno. Come posso fare
in modo che la mia interfaccia grafica funzioni senza doverla sempre modificare?
Per risolvere questo problema ci vengono in aiuto le interfacce. L'idea è questa: entrambi gli oggetti (Atleta e Squadra) rappresentano,
oltre alle loro peculiari caratteristiche, anche una voce di rubrica. In particolare nel contesto di VisualizzatoreRubrica
non ci interessa
nessuna altra informazione (non importa il tempo sui 100m per esempio).
new
) usato per specificare il comportamento
che deve avere una classe che lo implementa.
Quindi dalla definizione si capisce che da qualche parte l'interfaccia viene dichiarata e da qualche altra implementata.
Dichiarazione di una interfaccia
Una interfaccia si dichiara in un file come una normale classe ma sostituendo
class
con interface
.
Questa qui sotto è la nostra interfaccia:
public interface ElementoRubrica { public String getNome(); public String getNumero(); }
Cosa ha di strano questo file?
i metodi sono publiclo possono essere come nelle classi manca il corpo dei metodi giusto!Le interfacce a differenza delle classi non dicono come svolgere le azioni (cosa che nelle classi si fa nel corpo dei metodi) ma soltanto quali funzionalità un oggetto deve avere.
Implementazione di una interfaccia
Adesso dobbiamo dichiarare che il nostro Atleta si comporta anche come un ElementoRubrica:
dobbiamo cioè implementare l'interfaccia usando la parola chiave implements
.
public class Atleta implements ElementoRubrica { private String nome; private String numero; private double tempoCentoMetri; /* tutti gli altri metodi */ public String getNome() { return nome; } public String getNumero() { return numero; } }
Sebbene in Java sia possibile estendere una sola classe si possono però
implementare quante interfacce si vuole (separandone i nomi da ",").
Bisogna però tener presente che una interfaccia non può essere direttamente instanziata
cioè non posso creare un oggetto di tipo ElementoRubrica usando new
perché nella definizione dell'interfaccia io non ho definito il suo comportamento
(manca il corpo dei metodi).
Il vantaggio a questo punto è questo: nella mia classe VisualizzatoreRubrica
posso ignorare quale oggetto particolare devo visualizzare, mi interessa soltanto
che implementi l'opportuna interfaccia ElementoRubrica
. Il nostro
codice diventa:
class VisualizzatoreRubrica { /* altri metodi e variabili */ void visualizza(ElementoRubrica e){ campoNome.setText(e.getNome()); ... } }
Adesso al metodo visualizza()
non interessa quale tipo di oggetto viene passato ma
soltanto che implementi l'interfaccia ElementoRubrica
.
Se volessi implementare questa interfaccia anche nell'oggetto Allenatore
la mia interfaccia grafica non avrebbe bisogno di nessuna modifica e funzionerebbe comunque.