In questa lezione metteremo in atto i principi dell’incapsulamento esposti precedentemente. Come prima cosa bisogna rendere gli attributi della classe in maniera tale che non siano direttamente accessibili dall’esterno. Ciò si ottiene dichiarando gli attributi della classe usando il modificatore di visibilità private. Usando il private si rendono gi attributi della classi visibili solo ed esclusivamente all’interno della classe, dunque potranno manipolarli solo i metodi facente parte della stessa classe. Andiamo adesso a scrivere una classe che rappresenta un’anagrafica di una determinata persona:
public class Anagrafica {
private String nome;
private int annoDiNascita;
}
In questo modo abbiamo bloccato dall’esterno l’accesso diretto agli attributi, infatti nel caso in cui istanziassimo la classe e cercassimo di accedere all’atributo usando l’operatore "." riceveremo un errore del compilatore che ci avvertirà che le variabili "nome" e "annoDiNascita" non sono visibili.
Adesso non ci resta che creare un’interfaccia pubblica da utilizzare poi nella nostra classe di Implementazione per poter accedere ai dati. Estendiamo, quindi, il codice della classe "Anagrafica" nel seguente modo:
public class Anagrafica {
private String nome;
private int annoDiNascita;
public void setNome(String n) {
nome=n;
}
public String getNome() {
return nome;
}
public void setAnnoDiNascita(int anno) {
annoDiNascita=anno;
}
public int getAnnoDiNascita() {
return annoDiNascita;
}
}
Abbiamo dunque creato due interfacce pubbliche per ogni attributo della classe: uno per l’assegnazione del valore e uno per recuperare il valore dell’attributo.Adesso possiamo andare a scrivere la nostra classe di Implementazione:
public class Implementazione {
public static void Main(String args[]) {
Anagrafica anagrafica = new Anagrafica();
anagrafica.setNome("Matteo");
anagrafica.setAnnoDiNascita(1987);
}
}
Se eseguissimo la classe "Implementazione" assegneremo il valore "Matteo" alla variabile "nome" e il valore "1987" alla variabile "annoDiNascita".
Fino a questo momento non si vedono grossi vantaggi nell’utilizzo dell’incapsulamento, ma proviamo a pensare se volessimo fare un controllo sulla data di nascita per limitare l’accesso a qualche risorsa da parte degli utenti. Cosa dovremo andare a modificare? La risposta è semplice, dovremo esclusivamente andare a modificare il metodo "setAnnoDiNascita(int anno)" della classe "Anagrafica" lasciando totalmente inalterata la classe "Implementazione". Eseguiamo la modifica, per esempio accettando solo utenti nati nell’arco di tempo 1990-2000.
public void setAnnoDiNascita(int anno) {
if(anno >= 1990 && anno<=2000) {
annoDiNascita=anno;
}
else{
System.out.println("Non puoi accedere");
}
}
E' evidente nel caso avessimo più attributi e volessimo successivamente modificare le interfacce pubbliche magari facendo controlli più raffinati sull'input da parte dell'utente basterà modificare il codice relativo nella classe originaria senza toccare in alcun modo la classe di implementazione. Tutto ciò è in perfetto accordo con quanto espresso precedentemente riguardo il concetto di riuso del codice.
Fino a questo momento abbiamo ottenuto un incapsulamento per gli attributi della classe. Usando però il modificatore private applicato ad un metodo, di fatto si ottiene un incapsulamento funzionale. L'incampusulamento funzionale ha lo scopo di rendere ancora più semplice il codice dell'interfaccia di implementazione, per esempio creando un unica interfaccia pubblica per l'inizializzazione dei dati e poi nella classe originarie scrivere l'interfaccia pubblica in modo che contenga tutti i metodi "setNomeAttributo" relativi alla classe. In questo caso ogni metodo del tipo "setNomeAttributo" verrà dichiarato con modificatore di visibilità private per ottenere l'incapsulamento funzionale. In questo modo se si provasse ad accedere al metodo dall'esterno otterremo lo stesso errore di quando cercavamo di accedere dall'esterno ad un attributo della classe che era dichiarato privato.