|
XXX
  |
Definire un costruttore |
Fin qui non abbiamo fatto altro che creare un record, ovvero definirlo
(nel senso che abbiamo descritto come è fatto) e "allocarlo" (nel
senso che abbiamo riservato memoria per contenere i dati contenuti nel
record). Il limite della allocazione tradizionale è che riserva spazio
di memoria e basta. Generalmente la memoria allocata non basta per
potere utilizzare la struttura dati. Occorre inizializzarla in qualche
modo. Per esempio lo stack richieste che venga creato anche un array
contenuto dentro lo stack, e che il puntatore al primo elemento libero
dello stack (il "top") sia posto a zero. L'allocazione per esempio a
volte garantisce che la memoria sia a zero, ma non crea altri
oggetti. In programmazione strutturata, dopo aver allocato la memoria
il programmatore deve provvedere ad inizializzare la memoria in modo
che sia usabile dagli algoritimi.
  |
Legando il codice di inizializzazione all'allocazione |
Ora, il punto è che l'inizializzazione è concettualmente legata alla
allocazione di memoria. Spesso in programmazione strutturata si
scrivono funzioni di inizializazione che devono essere eseguite subito
dopo che la memoria è stata riservata. In programmazione ad oggetti si
fa un passo avanti.
  |
Evitando inizializzazioni esplicite |
class Stack {
int top;
int [] stack;
Stack () {
top=0;
stack = new int [10];
}
}
Il concetto è che quando si fabbrica un oggetto, questo deve essere
pronto all'uso. Se andiamo in negozio a comprare una radio, non ci
aspettiamo che ci vengano dati i pezzi da assemblare (a meno che non
si è un hobbista di elettronica...) Ci aspettiamo una radio completa,
assemblata e pronta all'uso. Così in programmazione ad oggetti, quando
creiamo un nuovo oggetto, questo viene creato pronto all'uso nell'atto
stesso di allorare la memoria. Più esattamente i costruttori sono
particolari tipi di metodi che vengono invocato su un'area di memoria
appena allocata. Come si vede in figura abbiamo esteso il nostro
record per effettuare le inizializzazioni. La prima caratteristica che
balza all'occhio è una procedura scritta dentro la classe. Per la
precisione la procedura è un metodo, posto all'interno di una classe e
obbligatoriamente con lo stesso nome della classe. Dentro abbiamo il
codice di inizializzazione dei campi.
  |
Adesso basta new Stack() per avere una istanza completa |
Con questa definizione, nell'eseguire una new, viene prima allota la
memoria e poi viene chiamato il costruttore che abbiamo
definito. Questo spiega definitivamente perché dopo una new c'è una
chiamata e non semplicemente il nome del nuovo tipo di dato: la
chiamata fa appunto le veci di inizializzare la struttura dati che il
programmatore sta richiedendo. In verità ci sono alcune cose ancora da
chiarire in particolare come fa il meotodo costruttore a trovare le
variabili da inizializzare. Una cosa che deve essere chiara subito e
che spesso induce in errore i programmatori avvezzi ad altri linguaggi
è il fatto che le variabili della classe (i campi) non sono affatto
variabili locali che socconmbono alla fine di un blocco, né tantomeno
sono variabili globali universamente disponibili: ma vediamo adesso in
dettaglio come funziona.
|