Servono a inizializzare i valori dei campi degli oggetti.
Vengono invocati automaticamente dopo che l'oggetto è stato creato.
p=new Point();
Si poteva anche fare:
System.out.println(new Point());
Viene creato l'oggetto e restituito il suo riferimento (l'indirizzo di memoria in cui si trova)
Si può invocare il costruttore in ogni punto del programma in cui serve un oggetto.
Questo tipo di costruzione mette dei valori iniziali nelle componenti:
Classe:
import java.awt.*; class NomeClasse { Point p; int x; }
Programma:
class ProvaCostr { public static void main(String args[]) { NomeClasse a; a=new NomeClasse(); System.out.println(a.p); System.out.println(a.x); } }
Stampa:
null 0
È possibile ridefinire il comportamento del costruttore.
import java.awt.*; class NomeClasse { Point p; int x; NomeClasse() { this.p=new Point(); this.p.move(10,20); this.x=100; } }
Uso lo stesso programma di prima:
class ProvaCostr { public static void main(String args[]) { NomeClasse a; a=new NomeClasse(); System.out.println(a.p); System.out.println(a.x); } }
Solo che ora stampa:
java.awt.Point[x=10,y=20] 100
class NomeClasse { ... NomeClasse() { istruzioni; } }
Se voglio un costruttore per la classe NewPoint, si deve chiamare NewPoint().
Il costruttore per Studente si chiama Studente(), ecc.
Si e no.
a=new NomeClasse();
Vengono fatte due cose:
Viene poi ritornato l'indirizzo della zona di memoria creata.
NomeClasse a; a=new NomeClasse(); // invocazione
classe NomeClasse { ... NomeClasse() { // def costruttore istruzioni;
Dopo NomeClasse a, ma prima di invocare il costruttore:
Notare che a contiene un valore indefinito.
Quando si invoca il costruttore:
La creazione viene fatta prima dell'esecuzione delle istruzioni del costruttore.
Quando si eseguono queste istruzioni, ho già l'oggetto:
NomeClasse() { this.p=new Point(); this.p.move(10,20); this.x=100; }
this indica l'oggetto che è stato creato.
Viene modificato l'oggetto.
Il valore di ritorno è l'indirizzo dell'oggetto che è stato appena creato.
Se ho fatto a=new NomeClasse(), questo indirizzo viene scritto in a
Quando faccio new NomeClasse() creo un oggetto.
Il metodo NomeClasse() della classe contiene solo
le istruzioni per inizializzare l'oggetto
(quando viene invocato, l'oggetto esiste già)
Quando creo un oggetto, posso mettere nelle componenti valori diversi da 0 e null.
Più utile: costruttore con argomenti.
Questi costruttori sono già definiti:
p=new Point();
Crea un oggetto punto di coordinate (0,0)
p=new Point(12,32);
Crea un oggetto punto di coordinate (12,32)
Assomiglia a un metodo.
class Abcd { int x; Point p; Abcd(int x, Point p) { this.x=x; this.p=p; } }
L'invocazione è come per i punti.
Point p; p=new Point(12,32); Abcd o; o=new Abcd(12, p);
Quando si invoca un metodo, viene fatta la copiatura dei parametri e poi si eseguono le istruzioni del metodo.
Nel caso dei costruttori, viene prima creato l'oggetto, e poi si esegue il costruttore come fosse un metodo.
C'è un passo in mezzo, in cui l'oggetto viene creato.
Il costruttore si usa per inizializzare le componenti degli oggetti.
Però può fare qualsiasi cosa fa un metodo.
Per esempio, può stampare una stringa:
class Abcd { int x; Point p; Abcd() { System.out.println("Questa e' una stringa"); } }
È sbagliato metodologicamente, ma si può fare.
Definire un costruttore con argomenti per la classe Studente
Argomenti: i tre valori iniziali.
class Studente { String nome; int eta; double media; ... }
Il nome del costruttore è uguale al nome della classe.
Non ha valore di ritorno.
Ha tre argomenti.
this indica l'oggetto che è stato appena creato.
class Studente { String nome; int eta; double media; Studente(String nome, int eta, double media) { this.nome=nome; this.eta=eta; this.media=media; } }
Notare che il parametro formale nome si poteva anche chiamare in una altro modo, per esempio a
Non c'è relazione fra il nome del parametro formale e la componente dell'oggetto.
Estendere la classe Point in modo che abbia un nuovo costruttore, che prende come argomento un rettangolo, e mette nel punto il suo centro.
Nota: la nuova classe si chiama NewPoint
Per estendere serve un nuovo nome:
class NewPoint extends Point { ... }
Si comincia con l'intestazione del metodo come al solito.
import java.awt.*; class NewPoint extends Point { NewPoint(Rectangle r) { ... } }
Si tratta quasi di un metodo come gli altri.
import java.awt.*; class NewPoint extends Point { NewPoint(Rectangle r) { this.x=r.x+r.width/2; this.y=r.y+r.height/2; } }
Calcolo, sulla base degli argomenti, i valori da mettere nelle componenti dell'oggetto appena creato.
import java.awt.*; class ProvaNewPoint { public static void main(String args[]) { Rectangle r; r=new Rectangle(10,10,20,30); NewPoint q; q=new NewPoint(r); System.out.println(q); } }
I costruttori non si ereditano.
import java.awt.*; class ProvaNewPoint { public static void main(String args[]) { NewPoint p; p=new NewPoint(2,4); NewPoint q; q=new NewPoint(); System.out.println(p); } }
Le due new NewPoint(...) danno errore.
Se voglio un costruttore, lo devo definire.
import java.awt.*; class NewPoint extends Point { NewPoint() { } NewPoint(int x, int y) { this.x=x; this.y=y; } NewPoint(Rectangle r) { this.x=r.x+r.width/2; this.y=r.y+r.height/2; } }
Se non ci sono costruttori, si assume che ci sia quello vuoto.
Se però metto un costruttore, quello vuoto (se serve) va definito.
class Esempio1 { int x; }
Si può fare new Esempio1();
class Esempio2 { int x; Esempio2(int a) { this.x=a; }
Si può fare new Esempio2(valore), ma non si può fare new Esempio2()
class Esempio3 { int x; Esempio3() { } Esempio3(int a) { this.x=a; }
Si possono fare tutte e due le cose.
Se voglio solo ``ereditare'' il costruttore: definisco il costruttore con super(args) come corpo:
import java.awt.*; class NewPoint extends Point { NewPoint() { super(); } NewPoint(int x, int y) { super(x, y); } NewPoint(Rectangle r) { this.x=r.x+r.width/2; this.y=r.y+r.height/2; } }
Di solito, conviene ridefinire il costruttore.
super(argomenti) invoca un costruttore della classe che è stata estesa
Quando si invoca il costruttore della superclasse, questa deve essere la prima istruzione del metodo.
import java.awt.*; class TriPoint extends Point { int z; TriPoint() { } TriPoint(int x, int y, int z) { super(x, y); this.z=z; } }
Quando un metodo non inizia con super(argomenti), si assume automaticamente super(), ossia il costruttore senza argomenti.
Come per i metodi, posso avere costruttori con argomenti in numero o tipo diverso:
NewPoint() NewPoint(int, int) NewPoint(Rectangle)
Definire i costruttori per Studente:
Si definiscono più costruttori.
class Studente { String nome; int eta; double media; Studente() { } Studente(String nome) { this.nome=nome; } Studente(String nome, int eta, double media) { this.nome=nome; this.eta=eta; this.media=media; } }
Tutti i costruttori, se non iniziano con super(argomenti), si considerano come se iniziassero con super().
Quindi, se si definisce una classe senza il costruttore senza argomenti, allora nelle sottoclassi bisogna chiamare esplicitamente super(argomenti) come prima istruzione.
Altrimenti, lui assume super(), che non esiste.
Fare cosí:
Nel caso di classi estese, si può usare
super
(per questo corso: non è necessario)
Di solito: gli argomenti sono i valori che vengono messi nelle componenti dell'oggetto creato (es. il costruttore di Studente qui sopra)
Qualche volta: permettono di capire i valori iniziali delle componenti (es. il rettangolo di cui si usavano i valori x e y per la classe NewPoint
In generale: il costruttore è come tutti gli altri metodi (può fare quello che vuole con gli argomenti)