Come già anticipato nel primo articolo su Java, i tre principali concetti dei linguaggi ad oggetti verranno trattati singolarmente. In questo articolo vedremo il primo, che prende il nome di incapsulamento. Questo strumento, è uno dei più importanti in Java, perché rende quest’ultimo linguaggio “robusto”. Il bravo programmatore, deve cercare di “nascondere” parte del codice che non vuole che sia modificato dall’utente, per esempio, pur rendendo accessibile a quest’ultimo attraverso altri meccanismi.
Ecco un piccolo esempio che chiarisce questo aspetto.
La maggior parte delle persone che sta leggendo questo articolo, avrà sicuramente un cellulare. Uno dei principali dispositivi presenti in uno smartphone è sicuramente la batteria, senza la quale non potrebbe funzionare il dispositivo. Chi ha progettato il sistema operativo per il cellulare, avrà sicuramente creato una funzionalità (interfaccia pubblica) con la quale il singolo utente è in grado di capire la percentuale di batteria disponibile. La percentuale della batteria sarebbe possibile anche calcolarla, smontando il dispositivo e utilizzando un tester (facendo la misura della tensione ai capi della batteria). Ma questo potrebbe causare il danneggiamento del dispositivo ! Il principio dell’incapsulamento è molto simile all’esempio precedente. Facciamo ora un esempio software. Facciamo che in un classe di un programma, ci sia del codice che permette di inserire una data. Tutti sanno che non tutti i mesi hanno 31 giorni, inoltre c’è un mese che ne ha 28. Quindi alcune date, come ad esempio 31/9 non sarebbe valido e quindi sono necessari alcuni controlli. Ecco il codice che mostra come non sia vantaggioso l’utilizzo dell’incapsulamento:
/** * Questa classe non sfrutta l'incapusalemtno. Dunque non è possibile effettuare controlli sull'inserimento di dati. * @author Giacomo */ package utils; public class DateSenzaIncapsulamento { public int year; public int month; public int day; public DateSenzaIncapsulamento(int year, int month, int day) { super(); this.year = year; this.month = month; this.day = day; } @Override public String toString(){ return day+"-"+month+"-"+year; } public static void main(String[] args) { DateSenzaIncapsulamento dateSenzaIncapsulamento = new DateSenzaIncapsulamento(2013, 9, 31); System.out.println(dateSenzaIncapsulamento); } }
A video viene stampata la data che l’utente ha inserito senza nessun controllo. Vediamo come dovrebbe essere la classe Date, con l’utilizzo dell’incapsulamento. Dal punto di vista del codice, questa condizione si trasforma nel rendere tutti gli attributi private e creare dei particolare metodi di tipo public, che permette all’utente di accedervi. Occorre notare che ci possono essere anche dei metodi private e non solo gli attributi.
/** * Questa classe permette di instanziare date. Viene ancora una volta mostrato il grande vantaggio che offre * l'incapsulamento, permettendo di fare controlli sui dati inseriti dall'utente. * @author Giacomo */ package utils; public class Date { private int year; private int month; private int day; public Date(int day, int month, int year){ setDay(day); setMonth(month); setYear(year); } public int getDay(){ return day; } public void setDay(int day){ int maxDay=31; switch(month){ case 2: maxDay=28; break; case 4: case 6: case 9: case 11: maxDay=30; break; default: break; } if(day<1){ verificaData(); day=1; }else if(day>maxDay){ verificaData(); day=maxDay; } this.day=day; } public int getMonth(){ return month; } public void setMonth(int month){ if(month<1){ verificaData(); month=1; } else if(month>12){ verificaData(); month=12; } this.month=month; setDay(this.day); } public int getYear(){ return year; } public void setYear(int year){ this.year=year; } public void verificaData(){ System.err.println("Attenzione, vefica il corretto inserimento della data"); } @Override public String toString(){ return getDay()+"-"+getMonth()+"-"+getYear(); } }
All’interno di questa cartella condivisa, è possibile trovare tutto il codice che è appena stato descritto.
Vediamo di capire un po’ meglio come funziona il codice appena scritto. Gli attributi che vengono inizializzati private rappresentano l’anno, il mese e il giorno di una data. Successivamente viene scritto il costruttore, che non è quello di default, dal momento che vengono inseriti direttamente i 3 valori che rappresentano la data. Inoltre all’interno delle parentesi graffe vengono impostati i 3 valori, attraverso i metodi set.
public Date(int day, int month, int year){ setDay(day); setMonth(month); setYear(year); }
All’interno dei metodi set, vengono fatti i relativi controlli. Questo permette di aumentare la robustezza del codice appena scritto, evitando che l’utente possa inserire date sbagliate ! Il metodo toString() serve per rappresentare con un certo layout la data inserita. La parola @Override verrà chiarita nella prossima puntata, quando parleremo dell’ereditarietà.
Conclusione
Come già spiegato nelle righe precedenti, l’incapsulamento permette di aumentare la robustezza del nostro codice, permettendo di accedere in modo controllato ad attributi o metodi. Il codice scritto in questo metodo, oltre che ad una migliore leggibilità, permette di essere utilizzato più volte nel corso del tempo.