13 - Metodi e Costruttori
Programmazione e analisi di dati Modulo A: Programmazione in Java
Paolo Milazzo
Dipartimento di Informatica, Universit`a di Pisa http://pages.di.unipi.it/milazzo
milazzo di.unipi.it
Corso di Laurea Magistrale in Informatica Umanistica A.A. 2016/2017
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 1 / 34
Dichiarazione di una classe
Lo schema generale di dichiarazione di una classe in Java `e il seguente:
p u b l i c c l a s s < nome - classe > {
< v a r i a b i l i di istanza >
< v a r i a b i l i s t a t i c h e >
< c o s t r u t t o r i >
< m e t o d i di istanza >
< m e t o d i statici >
}
Variabili e metodi (siano essi d’istanza o statici) sono chiamati anche membridella classe
L’ordine delle dichiarazioni all’interno del corpo di una classe non `e importante
Membri statici o di istanza? (1)
Abbiamo visto che si usano
membri d’istanzaper codificare lo stato e le funzionalit`a deisingoli oggetti
membri statici per codificare lo stato e le funzionalit`adella classe
I condivise da tutti gli oggetti
I significativi anche se non esiste nessun oggetto della classe
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 3 / 34
Membri statici o di istanza? (2)
Quindi:
Il metodo main `e statico. In effetti viene invocato prima di creare qualunque oggetto.
Una variabile dovrebbe essere d’istanza se assumevalori diversi per oggetti diversi.
I Esempio: base e altezza di un oggetto Rettangolo
Una variabile dovrebbe essere staticase assume gli stessi valori per oggetti diversi.
I In caso contrario potrebbe essere difficile mantere lo stesso valore per tale variabile in tutti gli oggetti.
Se un metodoutilizza una variabile d’istanzanon pu`o essere statico
I Il compilatore segnalerebbe un errore
I Il modificatore static per i metodi serve solo per far controllare al compilatore di non usare variabili d’istanza
Se un metodonon utilizzavariabili d’istanza dovrebbe essere statico
Modificatori di visibilit` a
Abbiamo visto che una dichiarazione di variabile o metodo (sia statico che di istanza) pu`o essere preceduto da modificatori di visibilit`a.
In ordine crescente di visibilit`a abbiamo:
private Utilizzabile solo all’interno della stessa classe senza modificatore Utilizzabile solo nelpackage che contiene la classe
protected Utilizzabile nelpackage che contiene la classe, e in tutte le classi che ereditanoda essa public Utilizzabile ovunque
Vedremo pi`u avanti i package e il concetto diereditariet`a
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 5 / 34
Interfaccia pubblica di una classe
I membri pubblici di una classe (compresi i costruttori) costituiscono l’interfaccia pubblicadella classe
E’ l’inseme delle risorse e delle funzionalit`a messe a disposizione delle altre classi
Invece:
Le variabili privatedi una classe rappresentano lo stato interno della classe
Imetodi privatidi una classe sono metodi ausiliaria disposizione degli altri metodi della classe
Metodi (1)
La dichiarazione di un metodo ha la seguente sintassi:
< m o d i f i c a t o r i > < tipo > < nome > ( < l i s t a _ p a r a m e t r i _ f o r m a l i >) { . . . .
}
Esempio:
p u b l i c s t a t i c int m i n i m o (int a , int b ) { if ( a < b ) r e t u r n a ;
e l s e r e t u r n b ; }
Modificatori: di visibilit`a (private, public, ...) o di appartenenza a classe o istanze (static)
Tipo: del risultato restituito dal metodo Nome: del metodo
Parametri formali: lista (anche vuota) di coppie
<tipo> <parametro>
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 7 / 34
Metodi (2)
I metodi e la possibilit`a di definire variabili private consentono di limitare l’accesso allo stato di un oggetto
p u b l i c c l a s s S o l a L e t t u r a { p r i v a t e int v a l o r e ;
p u b l i c S o l a L e t t u r a (int x ) { v a l o r e = x ;
}
p u b l i c int g e t V a l o r e () { r e t u r n v a l o r e ;
} }
La variabile d’istanza valore potr`a essere acceduta in sola lettura
Metodi (3)
Tramite i metodi si pu`o anche controllare la scrittura delle variabili private
p u b l i c c l a s s S o l a L e t t u r a { p r i v a t e int v a l o r e ;
p u b l i c S o l a L e t t u r a (int x ) { v a l o r e = x ;
}
p u b l i c int g e t V a l o r e () { r e t u r n v a l o r e ;
}
// m o d i f i c a il v a l o r e s o l o se il n u o v o e ’ m a g g i o r e // r e s t i t u i s c e t r u e se la m o d i f i c a e ’ s t a t a e f f e t t u a t a p u b l i c b o o l e a n s e t V a l o r e (int n u o v o ) {
if ( nuovo > v a l o r e ) { v a l o r e = n u o v o ; r e t u r n t r u e; }
e l s e
r e t u r n f a l s e; }
}
La modifica della variabile valore sar`a sotto controllo del metodo!
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 9 / 34
Incapsulamento (1)
La possibilit`a di controllare l’accesso allo stato degli oggetti tramite appositi metodi nei linguaggi orientati agli oggetti prende il nome di
Propriet`a di Incapsulamento
L’incapsulamento consente di nasconderela rappresentazione dello stato interno degli oggetti agli utilizzatori
L’utilzzatore di getValore e setValore non `e necessariamente a conoscenza che il valore `e rappresentato nella classe da una variabile di tipo int
La classe potrebbe ad esempio sfruttare un array di int che
memorizza (all’insaputa dell’utilizzatore) gli ultimi 10 valori ricevuti...
Incapsulamento (2)
Abbiamo gi`a discusso che l’incapsulamento `e una propriet`a essenziale per consentire lo sviluppo di applicazioni complesse
E’ sufficiente i vari programmatori si accordino sulle interfacce pubbliche delle varie classi che ogniuno deve implementare L’utilizzo della terminologia get... e set... per i metodi che consentono di accedere a variabili private `e una prassi comune:
getValue(), setValue(x), getFirstElement() getLastElement(), ...
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 11 / 34
Passaggio dei parametri
In Java il passaggio dei parametri ai metodi avviene per valore I metodi lavorano sucopie delle variabili passate come parametri E quando si passano oggettiai metodi?
Le variabili di tipo classe contengonoriferimenti a oggetti
Ci`o che viene copiato al momento della chiamata `e il riferimento!
Il metodo lavora sull’oggetto originale (acceduto tramite la copia del riferimento)
Riferimenti e incapsulamento: ATTENZIONE (1)
Assumendo che la classe Rettangolo sia la seguente:
p u b l i c c l a s s R e t t a n g o l o { p u b l i c int b a s e ;
p u b l i c int a l t e z z a
p u b l i c R e t t a n g o l o (int b , int a ) { b a s e = b ; a l t e z z a = a ; } }
Ragioniamo sulla seguente classe che usa Rettangolo:
p u b l i c F i n e s t r a {
// v a r i a b i l e a cui non v o g l i a m o d a r e a c c e s s o p u b b l i c o p r i v a t e R e t t a n g o l o a r e a ;
p u b l i c F i n e s t r a () {
a r e a = new R e t t a n g o l o ( 8 0 0 , 6 0 0 ) ; }
p u b l i c R e t t a n g o l o g e t A r e a () { r e t u r n a r e a ;
} }
La variabile privata area `e al sicuro?
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 13 / 34
Riferimenti e incapsulamento: ATTENZIONE (2)
Risposta: NO
Vediamo cosa potrebbe fare un utilizzatore della classe Finestra
p u b l i c c l a s s U s a F i n e s t r a {
p u b l i c s t a t i c v o i d m a i n ( S t r i n g [] a r g s ) { F i n e s t r a f = new F i n e s t r a ();
R e t t a n g o l o r = f . g e t A r e a ();
S y s t e m . out . p r i n t l n ( r . b a s e ); // s t a m p a 800 r . b a s e = 1 0 0 ;
R e t t a n g o l o r2 = f . g e t A r e a ();
S y s t e m . out . p r i n t l n ( r2 . b a s e ); // s t a m p a 100 }
}
Il metodo getArea() di Finestra restituisce un riferimento all’oggetto
Overloading (1)
Java supporta un meccanismo di overloading(sovraccarico) che consente di chiamare pi`u metodi della stessa classe con lo stesso nome, purch´e ogni metodo abbia una diversa firma (signature).
Dato un generico metodo:
< m o d i f i c a t o r i > < tipo > < nome > ( < tipo1 > < p1 > , ... , < tipon > < pn >) { ...
}
la firma corrispondente `e data dalla sequenza:
< nome >( < tipo1 > , ... , < tipon >)
Attenzione: la firma non comprende n´e iltipodel metodo, n´e inomidei parametri formali.
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 15 / 34
Overloading (2)
Esempi:
Metodo Firma
int getVal() getVal()
int minimo(int x, int y) minimo(int,int) int minimo(int a, int b) minimo(int,int) double minimo(double x, double y) minimo(double,double)
int minimo(int x, int y, int z) minimo(int,int,int) Quali di questi metodi potrebbero stare nella stessa classe?
Overloading (3)
Esempio:
p u b l i c c l a s s S o m m a t o r e {
p u b l i c s t a t i c int s o m m a (int x ) { r e t u r n x ;
}
p u b l i c s t a t i c int s o m m a (int x , int y ) { r e t u r n x + y ;
}
p u b l i c s t a t i c int s o m m a (int x , int y , int z ) { r e t u r n x + y + z ;
} }
La possibilit`a di usare l’overloadingdi un metodo consente di usare lo stesso nome per metodi diversi che realizzano la stessa funzionalit`asu dati di tipo diverso.
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 17 / 34
Varargs (1)
Recentemente (pi`u o meno) in Java `e stato introdotta la possibilit`a di definire metodi con un numero variabile di parametri
Metodi convarargs
Nelladefinizione di un metodo con varargs l’ultimo parametro formale ha la seguente sintassi:
< tipo > . . . par
dove i puntini sospensivi danno l’idea che il parametro attuale corrispondente pu`o essere presente zero o pi`u volte.
All’interno del corpo del metodo, il parametro par avr`a tipo <tipo>[]....
Attenzione: solo l’ultimo parametro formale di un metodo pu`o avere
Varargs (2)
Esempio:
p u b l i c c l a s s S o m m a t o r e {
p u b l i c s t a t i c int s o m m a (int... v a l o r i ) {
int s = 0;
for (int x : v a l o r i ) { s += x ;
}
r e t u r n s ; }
}
Utilizzo:
S y s t e m . out . p r i n t l n ( s o m m a ( ) ) ; // s t a m p a 0 S y s t e m . out . p r i n t l n ( s o m m a (3 ,4)); // s t a m p a 7
S y s t e m . out . p r i n t l n ( s o m m a (5 ,7 ,2 ,1 ,6 ,8 ,1)); // s t a m p a 30
La firma di int somma(int... valori) `e somma(int[])
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 19 / 34
Costruttori e inizializzazione di variabili
Fino ad ora abbiamo visto che uncostruttore`e un metodo speciale che viene eseguito al momento della creazione di un oggetto (tramite la primitivanew
Tipicamente inizializza le variabili di istanza dell’oggetto L’inizializzazione delle variabili in Java merita un discorso...
Inizializzazione di variabili (1)
Abbiamo visto due tipologie di variabili in Java
variabili dichiarate localmente nei metodi (o costruttori): variabili localie parametri formali
variabili dichiarate come membri di una classe: variabili statichee variabili d’istanza
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 21 / 34
Inizializzazione di variabili (2)
Le variabili locali dei metodi:
vengono allocate nel record di attivazione relativo alla chiamata del metodo (nello stack)
devono essere inizializzate esplicitamente, altrimenti il compilatore segnala un errore
Esempio:
int num ;
w h i l e ( num > = 0 ) {
num = i n p u t . n e x t I n t ();
}
Errore segnalato dal compilatore:
Inizializzazione di variabili (3)
Le variabili statiche e di istanza:
vengono allocate nell’area di memoria che descrive l’oggetto (nello heap)
vengono sempre inizializzate, anche se non viene fatto esplicitamente I valori di default di queste variabili sono:
0 per le variabili numeriche
false per le variabili di tipo boolean null per le variabili di tipo classe (oggetti)
Ci sono tre modiper inizializzare una variabile d’istanza o statica:
Con assegnamento esplicito all’interno di un costruttore;
Con inizializzazione esplicita nella dichiarazione;
Inizializzazione (implicita) con valori default.
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 23 / 34
Inizializzazione di variabili (4)
Esempio in cui tutti e tre i modi sono impiegati:
p u b l i c c l a s s P u n t o 3 d {
p u b l i c d o u b l e x ; // i n i z i a l i z z a z i o n e nel c o s t r u t t o r e p u b l i c d o u b l e y = 3 . 0 ; // i n i z i a l i z z a z i o n e n e l l a d i c h i a r a z i o n e p u b l i c d o u b l e z ; // i n i z i a l i z z a z i o n e con v a l o r e di d e f a u l t p u b l i c P u n t o 3 d (d o u b l e val ) {
x = val ; }
}
Esempio di uso
P u n t o 3 d p = new P u n t o 3 d ( 5 . 0 ) ;
S y s t e m . out . p r i n t l n ( p . x ); // s t a m p a 5 . 0 ; S y s t e m . out . p r i n t l n ( p . y ); // s t a m p a 3 . 0 ; S y s t e m . out . p r i n t l n ( p . z ); // s t a m p a 0 . 0 ;
Costruttori (1)
I costruttori si dichiarano all’interno di una classe essenzialmente come i metodi, ma rispettando le seguenti regole:
1. il nome del costruttore deve coincidere con quello della classe;
2. il tipo del costruttore non deve essere specificato.
3. il modificatore static non pu`o essere usato per un costruttore.
Come per i metodi, anche ai costruttori si applica l’overloading:
una classe pu`o avere pi`u costruttori purch´e abbiano firma diversa (cio`e i parametri formali devono differire nel tipo e/o nel numero).
Esempio (classe ContoCorrente):
p u b l i c C o n t o C o r r e n t e (d o u b l e s a l d o I n i z i a l e ) { s a l d o = s a l d o I n i z i a l e ;
}
p u b l i c C o n t o C o r r e n t e () { s a l d o = 0 . 0 ;
}
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 25 / 34
Costruttori (2)
Ogni classe ha un costruttore di default che inizializza le variabili d’istanza con il corrispondente valore di default
Questo costruttore non ha parametri, ed `e disponibile solo se nella classe non `e definito nessun costruttore
Se invece nella classe `e definitoalmeno un costruttore, allora il costruttore di default non `e pi`u utilizzabile
Esempio di classe senza costruttori:
p u b l i c c l a s s P u n t o { p u b l i c d o u b l e x , y ; ... // a l t r i m e t o d i ma ... // n e s s u n c o s t r u t t o r e }
Viene utilizzato il costruttore di default:
Costruttori (3)
Esempio di classe con costruttori:
p u b l i c c l a s s P u n t o { p u b l i c d o u b l e x , y ;
p u b l i c P u n t o (d o u b l e vx , d o u b l e vy ) { x = vx ;
y = vy ; }
... // a l t r i m e t o d i }
Il costruttore di default non si pu`o usare:
P u n t o p1 = new P u n t o (); // E R R O R E P u n t o p2 = new P u n t o (3.0 , 5 . 0 ) // OK
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 27 / 34
Costruttori (4)
Se il programatore vuole continuare a rendere disponbile un costruttore che non prevede parametri, deve implementarlo:
p u b l i c c l a s s P u n t o { p u b l i c d o u b l e x , y ;
p u b l i c P u n t o () {} // i n i z i a l i z z a z i o n e a u t o m a t i c a p u b l i c P u n t o (d o u b l e vx , d o u b l e vy ) {
x = vx ; y = vy ; }
... // a l t r i m e t o d i }
Questa volta si possono usare entrambi i costruttori
P u n t o p1 = new P u n t o (); // OK
P u n t o p2 = new P u n t o (3.0 , 5 . 0 ) // OK
Il riferimento “this” (1)
In ogni corpo di un metodo d’istanza (o di un costruttore) `e sempre disponbile la variabile this
`
e un riferimento all’oggetto su cui si invoca il metodo (o costruttore)
`
e detto anche parametro implicitodel metodo
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 29 / 34
Il riferimento “this” (2)
Il riferimento this pu`o essere usato per accedere alle variabili di istanza del metodo:
Senza this
p u b l i c c l a s s P u n t o { p u b l i c d o u b l e x , y ;
p u b l i c S t r i n g t o S t r i n g () {
r e t u r n " ( " + x + " , " + y + " ) ";
} }
Con this (equivalente al precedente)
p u b l i c c l a s s P u n t o { p u b l i c d o u b l e x , y ;
p u b l i c S t r i n g t o S t r i n g () {
Il riferimento “this” (3)
In realt`a this in alcuni casi `e utile:
Consente di usare come nome di parametro formale lo stesso nome di una variabile d’istanza
p u b l i c c l a s s P u n t o { p u b l i c d o u b l e x , y ;
p u b l i c P u n t o (d o u b l e x , d o u b l e y ) {
// a s s e g n a i p a r a m e t r i a l l e v a r i a b i l i d ’ i s t a n z a t h i s. x = x ;
t h i s. y = y ; }
}
L’uso di this pu`o rendere pi`u chiara la lettura del codice di classi complesse
e’ subito chiaro che si sta usando una variabile d’istanza
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 31 / 34
Il riferimento “this” (4)
this consente anche di scrivere metodi che restituiscono un riferimento all’oggetto corrente:
p u b l i c c l a s s P u n t o { p u b l i c d o u b l e x , y ; ... // c o s t r u t t o r i
// r e s t i t u i s c e il " m i n i m o " tra p e l ’ o g g e t t o c o r r e n t e p u b l i c P u n t o m i n i m o ( P u n t o p ) {
if ( ( p . x + p . y ) < (t h i s. x +t h i s. y )) r e t u r n p ;
e l s e
r e t u r n t h i s; }
}
E si usa cosi’
P u n t o p1 = new P u n t o (3.0 , 7 . 0 ) ;
Il riferimento “this” (5)
Infine, this (o meglio, this()) pu`o essere usato da un costruttore per chiamarne un’altro
Attenzione: questo uso `e consentito soltantocome prima istruzione del costruttore
Senza this()
p u b l i c c l a s s P u n t o { p u b l i c d o u b l e x , y ;
// p r e n d e un s o l o v a l o r e e lo a s s e g n a sia a x che a y p u b l i c P u n t o (d o u b l e z ) {
t h i s. x = z ; t h i s. y = z ; }
p u b l i c P u n t o (d o u b l e x , d o u b l e y ) { t h i s. x = x ;
t h i s. y = y ; }
}
Paolo Milazzo (Universit`a di Pisa) Programmazione - Metodi e Costruttori A.A. 2016/2017 33 / 34
Il riferimento “this” (6)
Con this()
p u b l i c c l a s s P u n t o { p u b l i c d o u b l e x , y ;
// p r e n d e un s o l o v a l o r e e lo a s s e g n a sia a x che a y p u b l i c P u n t o (d o u b l e z ) {
t h i s( z , z ); // c h i a m a l ’ a l t r o c o s t r u t t o r e }
p u b l i c P u n t o (d o u b l e x , d o u b l e y ) { t h i s. x = x ;
t h i s. y = y ; }
}