Buono sconto 4% su Toner e Cartucce agli utenti AZpoint. SU Iomiricarico.it!!
|
Si ringrazia Claudio De Sio per la concessione del materiale pubblicato in questo articolo.
|
Caratteristiche avanzate del linguaggio
Obiettivi:
Il Lettore al termine di questo capitolo dovrà essere in grado di
Saper definire ed utilizzare i costruttori sfruttando l’overload (unità 8.1).
Conoscere e saper sfruttare il rapporto tra i costruttori e il polimorfismo (unità 8.1).
Conoscere e saper sfruttare il rapporto tra i costruttori e l’ereditarietà (unità 8.2).
Saper definire ed utilizzare il reference super (unità 8.3)
Saper chiamare i costruttori con i reference this e super (unità 8.3).
Conoscere cosa sono le classi interne e le classi anonime (unità 8.4).
Unità didattica 8.1)
- Costruttori e polimorfismo
Nel modulo 2, abbiamo introdotto i metodi costruttori. Essi sono stati definiti come dei metodi speciali, in quanto hanno delle proprietà:
hanno lo stesso nome della classe cui appartengono
non hanno tipo di ritorno
sono chiamati automaticamente (e solamente) ogni volta che viene istanziato un oggetto della classe cui appartengono, relativamente a quell’oggetto
sono presenti in ogni classe.
Relativamente all’ultimo punto abbiamo anche definito il costruttore di default, come il costruttore che è introdotto in una classe dal compilatore al momento della compilazione, nel caso il programmatore non gliene abbia fornito uno in maniera esplicita.
Abbiamo anche affermato che solitamente un costruttore è utilizzato per inizializzare le variabili degli oggetti al momento dell’istanza. Per esempio consideriamo la seguente classe che fa uso dell’incapsulamento:
class Cliente
{
private String nome;
private String indirizzo;
private int numeroDiTelefono;
public void setNome(String n)
{
nome=n;
}
public void setIndirizzo(String ind)
{
indirizzo=ind;
}
public void setNumeroDiTelefono(String num)
{
NumeroDiTelefono =num;
}
public String getNome()
{
return nome;
}
public String getIndirizzo()
{
return indirizzo;
}
public int getNumeroDiTelefono()
{
return numeroDiTelefono;
}
}
Il lettore potrà facilmente intuire la difficoltà di utilizzare le istanze di questa classe. Infatti, per creare un cliente significativo, dopo averlo istanziato, dovremo chiamare tre metodi per inizializzare le relative variabili:
Cliente cliente1= new Cliente();
cliente1.setNome("James Gosling");
cliente1.setIndirizzo("Palo Alto, California");
cliente1.setNumeroDiTelefono(0088993344556677);
Nella classe Cliente possiamo però inserire il seguente costruttore:
class Cliente
{
private String nome;
private String indirizzo;
private int numeroDiTelefono;
//il seguente è un costruttore
public Cliente(String n,String ind,int num)
{
nome=n;
indirizzo=ind;
numeroDiTelefono=num;
}
public void setNome(String n)
{
. . . . . . . . . . . . . .
Notare che il costruttore ha lo stesso nome della classe, e che non è stato dichiarato il tipo di ritorno. Per chiamare questo costruttore basta istanziare un oggetto dalla classe cliente passando i dovuti parametri nel modo seguente:
Cliente cliente1= new Cliente("James Gosling", "Palo Alto,
California",0088993344556677);
N.B.: nell’esempio precedente, l’introduzione del costruttore esplicito, implica la scomparsa del costruttore di default e la conseguente impossibilità d’istanziare oggetti con la seguente sintassi:
Cliente cliente1= new Cliente();
infatti, in questo modo, si tenterebbe di chiamare un costruttore inesistente.
- Overload dei costruttori:
Anche essendo metodi particolari, i costruttori sono comunque metodi. È possibile quindi, ed è fortemente consigliato, utilizzare l’overload dei costruttori. Infatti, nell’esempio precedente, dato che abbiamo inserito un costruttore esplicitamente, il compilatore non ha inserito il costruttore di default. A questo punto non sarà più possibile ovviamente, istanziare un oggetto senza passare parametri al costruttore. In compenso possiamo aggiungere altri costruttori alla classe, anche uno senza parametri, in maniera tale da poter costruire oggetti in modo differente in fase di runtime. Per esempio:
class Cliente
{
private String nome;
private String indirizzo;
private int numeroDiTelefono;
public Cliente(String n,String ind,int num)
{
nome=n;
indirizzo=ind;
numeroDiTelefono=num;
}
public Cliente(String n)
{
nome=n;
}
public Cliente(String n,String ind)
{
nome=n;
indirizzo=ind;
}
. . . . . . . . . . . . . .
public void setNome(String n)
{
. . . . . . . . . . . . . .
- Override dei costruttori:
Ricordiamo che l’override ci consente di riscrivere un metodo ereditato da una superclasse. Ma, alle caratteristiche di un costruttore, dobbiamo aggiungerne un’altra:
non è ereditato dalle sottoclassi
Infatti, se per esempio la classe Punto3d ereditasse della classe Punto, il costruttore Punto(), quest’ultimo non si potrebbe invocare, giacché la sintassi per istanziare un oggetto dalla classe Punto3d,
Punto3d punto = new Punto3d();
chiamerà sempre un costruttore della classe Punto3d.
Possiamo concludere che non potendo ereditare costruttori, non si può parlare di override di costruttori.
|