Costruttori in Java
- I costruttori sono metodi speciali utilizzati per inizializzare gli oggetti al momento della loro creazione.
- Un costruttore ha lo stesso nome della classe e non ha un tipo di ritorno.
- I costruttori possono accettare parametri per personalizzare l'inizializzazione degli oggetti.
- Se non viene definito un costruttore, Java fornisce un costruttore di default che inizializza le variabili di istanza ai valori predefiniti (zero,
null
,false
).
Costruttori
Riprendiamo l'esempio della classe Scatola
che abbiamo visto in precedenza:
class Scatola {
double larghezza;
double altezza;
double profondita;
}
In questo esempio, la classe Scatola
ha tre variabili di istanza: larghezza
, altezza
e profondita
. Queste variabili sono utilizzate per memorizzare le dimensioni della scatola. Tuttavia, non sono inizializzate, il che significa che quando si crea un oggetto Scatola
, queste variabili non hanno valori definiti.
Vi sono vari metodi per inizializzare le variabili di istanza di un oggetto. Un modo semplice ma sconveniente è quello di inizializzare i campi manualmente:
Scatola miaScatola = new Scatola();
// assegna valori alle variabili d'istanza di miaScatola
miaScatola.larghezza = 10;
miaScatola.altezza = 20;
miaScatola.profondita = 15;
Oppure, si può definire un metodo di convenienza per impostare le dimensioni della scatola:
class Scatola {
double larghezza;
double altezza;
double profondita;
// metodo di convenienza per impostare le dimensioni della scatola
void impostaDim(double l, double a, double p) {
larghezza = l;
altezza = a;
profondita = p;
}
}
Può essere noioso inizializzare tutte le variabili in una classe ogni volta che viene creato un oggetto. Il problema è che stiamo separando la creazione dell'oggetto dalla sua inizializzazione.
Anche aggiungendo metodi di convenienza come impostaDim()
, sarebbe più semplice e conciso avere tutta la configurazione fatta al momento in cui l'oggetto viene creato per la prima volta.
Poiché il requisito di inizializzazione è così comune, Java permette agli oggetti di inizializzarsi automaticamente quando vengono creati. Questa inizializzazione automatica è eseguita tramite l'uso di un costruttore.
Un costruttore inizializza un oggetto immediatamente alla creazione. Ha lo stesso nome della classe in cui risiede ed è sintatticamente simile a un metodo.
Una volta definito, il costruttore viene chiamato automaticamente quando l'oggetto viene creato, prima che l'operatore new
completi l'operazione. I costruttori possono sembrare un po' strani perché non hanno un tipo di ritorno, nemmeno void
. Questo perché il tipo di ritorno implicito del costruttore di una classe è il tipo della classe stessa.
È compito del costruttore inizializzare lo stato interno di un oggetto affinché il codice che crea un'istanza abbia a disposizione un oggetto completamente inizializzato e utilizzabile immediatamente.
Si può rielaborare l'esempio di Scatola
in modo che le dimensioni della scatola siano inizializzate automaticamente quando l'oggetto è costruito. A tal fine, sostituire impostaDim()
con un costruttore. Si comincia definendo un costruttore semplice che imposta le dimensioni di ogni scatola agli stessi valori. Questa versione è mostrata qui:
/* Qui, Scatola usa un costruttore per inizializzare
le dimensioni di una scatola.
*/
class Scatola {
double larghezza;
double altezza;
double profondita;
// Questo è il costruttore per Scatola.
Scatola() {
System.out.println("Costruzione di Scatola");
larghezza = 10;
altezza = 10;
profondita = 10;
}
// calcola e restituisce il volume
double volume() {
return larghezza * altezza * profondita;
}
}
class DimostrazioneScatola6 {
public static void main(String[] args) {
// dichiarare, allocare e inizializzare oggetti Scatola
Scatola miaScatola1 = new Scatola();
Scatola miaScatola2 = new Scatola();
double volume;
// ottenere il volume della prima scatola
volume = miaScatola1.volume();
System.out.println("Il volume è " + volume);
// ottenere il volume della seconda scatola
volume = miaScatola2.volume();
System.out.println("Il volume è " + volume);
}
}
Quando questo programma viene eseguito, genera i seguenti risultati:
Costruzione di Scatola
Costruzione di Scatola
Il volume è 1000.0
Il volume è 1000.0
Come si può vedere, sia miaScatola1
che miaScatola2
sono state inizializzate dal costruttore Scatola()
quando sono state create.
Poiché il costruttore assegna a tutte le scatole le stesse dimensioni, 10 per 10 per 10, sia miaScatola1
che miaScatola2
avranno lo stesso volume.
L'istruzione println()
all'interno di Scatola()
è solo a scopo illustrativo. La maggior parte dei costruttori non visualizzerà nulla. Si limiteranno a inizializzare un oggetto.
Prima di procedere, si riveda l'operatore new
. Come è noto, quando si alloca un oggetto, si utilizza la seguente forma generale:
variabile_classe = new nomeClasse();
Ora si può capire perché le parentesi sono necessarie dopo il nome della classe. Quello che sta realmente accadendo è che viene chiamato il costruttore della classe. Quindi, nella riga
Scatola miaScatola1 = new Scatola();
new Scatola()
sta chiamando il costruttore Scatola()
.
Quando non si definisce esplicitamente un costruttore per una classe, Java crea un costruttore di default per la classe. Questo è il motivo per cui la riga di codice vista nelle versioni precedenti di Scatola
che non definivano un costruttore, funzionava comunque.
Quando si usa il costruttore di default, tutte le variabili di istanza non inizializzate avranno i loro valori predefiniti, che sono: zero, null
e false
, rispettivamente per i tipi numerici, i tipi riferimento e i tipi boolean
.
Il costruttore di default è spesso sufficiente per classi semplici, ma solitamente non basta per quelle più sofisticate. Una volta definito un costruttore proprio, il costruttore di default non viene più utilizzato.
Costruttori con Parametri
Anche se il costruttore Scatola()
nell'esempio precedente inizializza effettivamente un oggetto Scatola
, non è molto utile: tutte le scatole hanno le stesse dimensioni.
Quello che serve è un modo per costruire oggetti Scatola
con dimensioni diverse. La soluzione più semplice è aggiungere parametri al costruttore. Come si può facilmente intuire, questo lo rende molto più utile. Ad esempio, la versione seguente di Scatola
definisce un costruttore parametrizzato che imposta le dimensioni di una scatola secondo i parametri specificati. Prestare particolare attenzione a come vengono creati gli oggetti Scatola
.
/*
* Qui, Scatola usa un costruttore parametrizzato per
* inizializzare le dimensioni di una scatola.
*/
class Scatola {
double larghezza;
double altezza;
double profondita;
// Questo è il costruttore per Scatola.
Scatola(double l, double a, double p) {
larghezza = l;
altezza = a;
profondita = p;
}
// calcola e restituisce il volume
double volume() {
return larghezza * altezza * profondita;
}
}
class DimostrazioneScatola {
public static void main(String[] args) {
// dichiarare, allocare e inizializzare oggetti Scatola
Scatola miaScatola1 = new Scatola(10, 20, 15);
Scatola miaScatola2 = new Scatola(3, 6, 9);
double volume;
// ottenere il volume della prima scatola
volume = miaScatola1.volume();
System.out.println("Il volume è " + volume);
// ottenere il volume della seconda scatola
volume = miaScatola2.volume();
System.out.println("Il volume è " + volume);
}
}
L'output di questo programma è mostrato qui:
Il volume è 3000.0
Il volume è 162.0
Come si può vedere, ogni oggetto è inizializzato come specificato nei parametri del suo costruttore. Ad esempio, nella seguente riga,
Scatola miaScatola1 = new Scatola(10, 20, 15);
i valori 10, 20 e 15 sono passati al costruttore Scatola()
quando new
crea l'oggetto. Così, la copia di miaScatola1
di larghezza
, altezza
e profondita
conterrà rispettivamente i valori 10, 20 e 15.