Il Lettore al termine di questo capitolo dovrà essere in grado di
Saper utilizzare tutti i modificatori d’accesso (unità 9.1, 9.2) .
Saper dichiarare ed importare package (unità 9.3).
Saper utilizzare il modificatore final (unità 9.4).
Saper utilizzare il modificatore static (unità 9.5).
Saper utilizzare il modificatore abstract (unità 9.6).
Comprendere l’utilità di classi astratte ed interfacce (unità 9.6, 9.7).
Comprendere e saper utilizzare l’ereditarietà multipla(unità 9.7).
Unità didattica 9.1)
- Modificatori fondamentali
Un modificatore, è una parola chiave capace di modificare in qualche modo,
il significato di un componente di un’applicazione Java. Anche essendo
fondamentale, non sempre l’utilizzo di un modificatore ha un chiaro
significato per il programmatore. Non è raro leggere programmi Java che
abusano di modificatori senza un particolare motivo. Si possono ovviamente
anteporre alla dichiarazione di un componente anche più di un modificatore
alla volta, senza tener conto dell’ordine in cui vengono ordinati tali
modificatori. Una variabile dichiarata static e public avrà quindi le stesse
proprietà di una dichiarata public e static. Il seguente schema riassume le
associazioni tra la lista completa dei modificatori, e i relativi componenti
a cui si possono applicare:
Notare che con la sintassi "(default)" vogliamo indicare la situazione in
cui non anteponiamo alcun modificatore alla dichiarazione di un componente.
In questo modulo presenteremo solo alcuni dei modificatori fondamentali che
Java mette a disposizione, tutti gli altri, riguardano argomenti avanzati
che non saranno trattati. Inizieremo la nostra carrellata dai cosiddetti
modificatori di accesso (detti anche specificatori d’accesso), con i quali
abbiamo già una discreta familiarità. Ne approfitteremo per puntualizzare il
discorso sull’utilizzo dei package.
Unità didattica 9.2)
- Modificatori d’accesso
I modificatori di accesso regolano essenzialmente l’accesso ad un componente
Java:
- public:
Può essere utilizzato sia relativamente ad un membro (attributo o metodo) di
una classe, sia relativamente ad una classe stessa. Abbiamo già
abbondantemente visto l’utilizzo relativo ad un membro di una classe.
Sappiamo oramai bene, che un membro dichiarato pubblico, sarà accessibile da
una qualsiasi classe situata in qualsiasi package.
Una classe dichiarata pubblica, sarà anch’essa visibile da un qualsiasi
package.
- protected:
Questo modificatore definisce per un membro, il grado più accessibile dopo
quello definito da public. Un membro protetto, sarà infatti accessibile
all’interno dello stesso package, ed in tutte le sottoclassi della classe in
cui è definito, anche se non appartenenti allo stesso package.
- default:
Se non anteponiamo modificatori d’accesso ad un membro di una classe, esso
sarà accessibile solo da classi appartenenti al package dove è definito. Se
dichiariamo una classe appartenente ad un package, senza anteporre alla sua
definizione il modificatore public, essa sarà visibile solo dalle classi
appartenenti allo stesso package. Possiamo considerare allora anche un
incapsulamento di secondo livello.
- private:
Questo modificatore restringe la visibilità di un membro di una classe alla
classe stessa.
Il tutto è riassunto nella seguente tabella riguardante i modificatori di
accesso e la relativa visibilità (solo per i membri di una classe):
Unità didattica 9.3)
- Gestione dei package
Abbiamo visto come la libreria standard di Java sia organizzata in package.
Questo ci permette di consultare la documentazione in maniera più
funzionale, potendo ricercare le classi che ci interessano, limitandoci al
package di appartenenza. Grazie ai package il programmatore ha quindi la
possibilità di organizzare anche le classi scritte da lui medesimo. È molto
semplice infatti, dichiarare una classe appartenente ad un package. La
parola chiave package ci permette di specificare, prima della dichiarazione
della classe (l’istruzione package deve essere assolutamente la prima in un
file Java) il package di appartenenza. Ecco un frammento di codice che ci
mostra la sintassi da utilizzare:
package programmi.gestioneClienti;
class AssistenzaClienti
{
. . . . .
In questo caso la classe AssistenzaClienti apparterrà al package
gestioneClienti, che a sua volta appartiene al package programmi. I package
fisicamente saranno cartelle (directory). Ciò significa che, dopo aver
dichiarato la classe appartenente a questo package, dovremo inserire la
classe compilata all’interno di una cartella chiamata gestioneClienti,
situata a sua volta all’interno di una cartella chiamata programmi. Di
solito il file sorgente va tenuto separato dalla classe compilata così come
schematizzato di seguito, dove abbiamo idealizzato i file con ovali, e le
directory con rettangoli:
Il Java Development Kit ci permette comunque di realizzare il giusto
inserimento dei file nelle cartelle, e la relativa creazione automatica
delle cartelle stesse, mediante il comando: javac –d . AssistenzaClienti.java
Lanciando il suddetto comando dalla cartella di base (dove è situato il file
AssistenzaClienti.java), verranno quindi automaticamente create le cartelle
programmi e gestioneClienti, ed il file AssistenzaClienti.class collocato
nella cartella giusta, senza però spostare il file sorgente dalla cartella
di base. A questo punto, supponendo che il file in questione contenga il
metodo main, potremmo mandarlo in esecuzione solo posizionandoci nella
cartella di base e lanciando il comando:
java programmi.gestioneClienti.AssistenzaClienti
infatti, a questo punto, il file è associato ad un package e non potrà
essere più chiamato spostandosi nella cartella dove esso è presente
utilizzando il comando:
java AssistenzaClienti
Inoltre, bisogna utilizzare un comando di import per utilizzare tale classe
da un package differente.
Esistono altri problemi collegati all’utilizzo di package, che l’aspirante
programmatore potrà incontrare, e risolvere con l’aiuto dei messaggi di
errore ricevuti dal compilatore. Per esempio potrebbe risultare problematico
riuscire ad utilizzare delle classi appartenenti ad un package, da una
cartella non direttamente legata al package stesso. Ciò è risolvibile
mediante l’impostazione della variabile di ambiente "classpath" del sistema
operativo, che dovrebbe puntare alla cartella di base relativa al package
stesso.
N.B.: sebbene semplice da spiegare, la gestione dei package può risultare
molto difficoltosa e soprattutto noiosa se "fatta a mano". Se il lettore è
arrivato sino a questo punto utilizzando uno strumento come il blocco note
per esercitarsi, vuol dire che ora è pronto per passare ad utilizzare un
editor più sofisticato. Un qualsiasi editor Java, anche il più semplice,
gestisce l’organizzazione dei package in maniera automatica…
Unità didattica 9.4)
- Il modificatore final
Questo semplice modificatore ha un’importanza fondamentale. È applicabile
sia a variabili, sia a metodi, sia a classi. Potremmo tradurre il termine
final proprio con "finale", nel senso di "non modificabile". Infatti:
una variabile dichiarata final diviene una costante.
un metodo dichiarato final non può essere riscritto in una sottoclasse (non
è possibile applicare l’override).