SISSIS MODULO DI JAVA PER LA CLASSE IV DELL’ITI UNITA’ DIDATTICA 4 UN’ANALISI APPROFONDITA DEI METODI E DELLE CLASSI di Doretta Bonura Corso di fondamenti di Informatica: IV ciclo prof. Domenico Cantone PREREQUISITI _____________________________________________ Familiarità in Java con: Tipi di dati Operatori Costrutti principali Concetto di classe e oggetti Struttura sintattica delle classi e dei metodi UD 4: I metodi in java UN’ANALISI APPROFONDITA DEI METODI E DELLE CLASSI OBIETTIVI ________________________________________________________ Guidare lo studente ad acquisire una mentalità di programmazione O.O. mostrando le potenzialità degli strumenti di programmazione che Java mette a disposizione in questa direzione: LA PAROLA RISERVATA this SOVRACCARICO DEI METODI OGGETTI COME PARAMETRI EREDITARIETA’ RIDEFINIZIONE DEI METODI CLASSI ASTRATTE E METODI ASTRATTI UD 4: I metodi in java STRUMENTI ________________________________________________________ LIBRO DI TESTO APPUNTI DEL PROFESSORE TUTORIAL SU INTERNET LABORATORIO Nota: testi di riferimento usati per queste slides: JAVA GUIDA COMPLETA - Patrick Naughton, Herbert Shildt – Mc Graw Hill JAVA GUDA COMPLETA – Laura Lemay, Charles L. Perkins - APOGEO UD 4: I metodi in java METODOLOGIE DI LAVORO: _________________________________________________________ Lezione frontale Esercitazioni di laboratorio Esercitazioni in classe Esercitazioni a casa con esercizi e piccoli progetti. Verifiche in classe scritte e orali UD 4: I metodi in java TEMPI TOTALE: 3 SETTIMANE ore Lezione frontale Esercitazioni di laboratorio Esercitazioni in classe Verifiche in classe scritte e orali Esercitazioni a casa UD 4: I metodi in java 8 9 4 6 15 LA PAROLA RISERVATA this Nel corpo di un metodo può presentarsi la necessità di far riferimento all’oggetto corrente, cioè quello su cui verrà richiamato il metodo, quando l’oggetto verrà creato. In questi casi si usa la parola chiave this che permette di far riferimento all’oggetto corrente, prima ancora che esso venga istanziato. Esso puo’ essere usato in diverse situazioni: ------------------------------------------------------------------------------ Nei metodi costruttori. Per restituire l’oggetto stesso all’interno di un metodo. Per far riferimento da parte di un metodo ad un altro metodo dichiarato all’interno della stessa classe. -----------------------------------------------------------------------------------Poiché il this è un riferimento all’istanza corrente di una classe lo si può utilizzare solo nei metodi si istanza, non nei metodi di classe (quelli dichiarati come static). L’omissione del this per far riferimento alle variabili di istanza nel corpo di un metodo è possibile se non esistono variabili locali con lo stesso nome delle variabili di istanza, altrimenti si farà precedere il riferimento alla variabile di istanza dalla parola riservata this. Vediamo subito un esempio. UD4: I metodi in java UTILIZZO DEL this NEI METODI COSTRUTTORI //*************** file: Rettangolo.java public class Rettangolo { double base; // var di istanza double altezza; // var di istanza //----- metodo costruttore ----Rettangolo( double b, double a) { base = b; altezza =a; } } //fine classe Rettangolo //*************** file: Rettangolo.java public class Rettangolo { double base; // var di istanza double altezza; // var di istanza //----- metodo costruttore----Rettangolo( double base, double altezza) { this.base = base; this.altezza = altezza; } } //fine classe Rettangolo Nel primo riquadro, per assegnare un valore alle variabili di istanza base e altezza, si è dovuto assegnare un altro nome ai parametri del metodo costruttore, in quanto, se si assegnasse lo stesso nome, all’interno del metodo le variabile di istanza sarebbero mascherate e non sarebbero visibili. Nel secondo riquadro vediamo che le variabili di istanza e i parametri del metodo costruttore hanno lo stesso nome.Quindi la variabile locale nasconde la variabile di istanza. In realtà java permette di far riferimento alle variabili di istanza all’interno del metodo utilizzando il this. Queste due classi sono equivalenti e l’utilizzo o no del this nei metodi costruttori dipende dalle preferenze del programmatore. UD4: I metodi in java UTILIZZO DEL this PER RESTITUIRE L’OGGETTO CORRENTE IN UN METODO //*************** file: Rettangolo.java public class Rettangolo { double base; // var di istanza double altezza; // var di istanza //----- metodo costruttore----Rettangolo( double base, double altezza) { this.base = base; this.altezza =altezza; } //----- metodo cambiadimA ----void cambiadimA( int scalare) { base = base * scalare; altezza =altezza * scalare; } //----- metodo cambiadimB ----Rettangolo cambiadimB( int scalare) { base = base * scalare; altezza = altezza * scalare; return this; //oggetto corrente } } //fine classe Rettangolo UD4: I metodi in java I due metodi cambiadimA e cambiadimB eseguono le stesse operazioni però il primo non restituisce niente, mentre il secondo restituisce l’oggetto stesso. Nel main verranno richiamati con modalità diverse. //********** file: ProvaRettangolo.java ****** public class ProvaRettangolo { //----------------- metodo main --------------public static void main ( String args[]) { Rettangolo r = new Rettangolo(1, 2); r.cambiadimA( 3 ); r = r.cambiadimB( 5 ); } } //fine classe ProvaRettangolo UTILIZZO DEL THIS PER FAR RIFERIMENTO AD UN ALTRO METODO ALL’INTERNO DELLA CLASSE STESSA //*************** file: Triangolo.java public class Triangolo { double a; // var di istanza double b; // var di istanza double c; // var di istanza //----- metodo costruttore con i lati come parametri Triangolo( double , double b, double c) { this.a = a; this.b = b; this.c = c; } //----- metodo perimetro ----double perimetro( ) { return ( a+b+c ); } //----- metodo area con formula di Erone double area ( ) { double area; double p; //semiperimetro p = this.perimetro( ) / 2; area = Math.sqrt( ( p-a) * (p-b) * (p-c) ); return area; } } //fine classe Triangolo UD4: I metodi in java Nel riquadro accanto, all’interno del metodo area viene calcolato il semiperimetro utilizzando il metodo perimetro definito in un altro metodo della stessa classe. Il this permette quindi di far riferimento all’oggetto corrente prima che esso venga creato. //********** file: ProvaTriangolo.java ****** public class ProvaTriangolo { //----------------- metodo main --------------public static void main( String args[ ]) { double area; Triangolo t = new Triangolo(4, 5, 6); area = t.area( ); } } //fine classe ProvaTriangolo Nel main posso richiamare il metodo area direttamente sull’oggetto t, Il metodo perimetro, richiamato dal metodo area sarà automaticamente eseguito sullo stesso oggetto t. SOVRACCARICO (OVERLOAD) DEI METODI Il sovraccarico dei metodi è uno dei modi in cui Java implementa il polimorfismo. E’ possibile definire due o più metodi aventi lo stesso nome all’interno della stessa classe purché si distinguano per il numero dei parametri, nota bene: non per il tipo dei parametri o per il tipo di ritorno. Vediamo un esempio: UD4: I metodi in java SOVRACCARICO DEI METODI esempio: //*************** file: Scrittura.java ***************************************************************** public class Scrittura { //--------------------------------------- metodo scrivi con 1 parametro ----void scrivi( String s1) { System.out.println(s1); } //-------------------------------------metodo scrivi con 2 parametri -----void scrivi( String s1, String s2) { System.out.println(s1+ s2); } } //fine classe Scrittura //****************** file: ProvaScrittura.java ***************************************************** public class ProvaScrittura { //------------------------------------- metodo main --------------public static void main void ( String args[ ]) { Scrittura frase = new Scrittura( ); //viene usato il metodo costruttore di default frase.scrivi(“Ciao a tutti”); frase.scrivi(”BUON NATALE ”,” FELICE ANNO NUOVO”); } } // fine classe ProvaScrittura ______________________________________________________________ Questo programma genera il seguente output: Ciao a tutti BUON NATALE UD4: I metodi in java FELICE ANNO NUOVO SOVRACCARICO DEI METODI COSTRUTTORI Il sovraccarico dei metodi costruttori segue le stesse regole dei metodi in generale, bisogna ricordare pero’ che il metodo costruttore di default, senza parametri non potrà più essere utilizzato. Si può ovviare a questo inconveniente ridefinendo il metodo costruttore di default. //*************** file: Punto.java *********************************************************** public class Punto { double x ; // variabili di istanza double y ; double z ; //------------------- metodo costruttore con 3 parametri ----------------------Punto(double x, double y, double z) { // costruisce un punto nello spazio XYZ this.x = x; this.y = y; this.z = z; } //------------------- metodo costruttore con 2 parametri---------------Punto( double x, double y) { // costruisce un punto nel piano Z=0 this.x = x; this.y = y; this.z = 0; } //-------------------- metodo costruttore senza parametri ---------Punto( ) { // ridefinizione del metodo costruttore di default, costruisce il punto origine this.x = 0; this.y = 0; this.z = 0; } //----------------------------------------------------------------------------} //fine classe Punto UD4: I metodi in java SOVRACCARICO DEI METODI COSTRUTTORI Vediamo come vengono creati gli oggetti della classe Punto nel main //*************** file: ProvaPunto.java ********************************************************************* public class ProvaPunto { public static void main ( String args[]) { Punto origine = new Punto( ); Punto p1_2d = new Punto(3,4); Punto p1_3d = new Punto(3,4,5); //viene costruito l’oggetto Punto origine = (0,0,0) //viene costruito l’oggetto Punto p1_2d = (3,4,0) //viene costruito l’oggetto Punto p1_2d = (3,4,5) System.out.println(“Il punto p1_2d ha coordinate:”); System.out.println(“X = “ + p1_2d.x); System.out.println(“Y = “ + p1_2d.y); System.out.println(“Z = “ + p1_2d.z); } } // fine classe ProvaPunto ______________________________________________________________ Questo programma genera il seguente output: Il punto p1_2d ha coordinate: X=3 Y=4 Z=0 UD4: I metodi in java UTILIZZO DEGLI OGGETTI COME PARAMETRI E’ possibile passare degli oggetti ai metodi //*************** file: Circonferenza.java public class Circonferenza { Punto centro; // var di istanza double raggio ; // var di istanza //*************** file: ProvaCirconferenza.java public class ProvaCirconferenza { public static void main ( String args[ ]) { // metodo costruttore riceve come parametri // un oggetto Punto e un tipo double. Circonferenza( Punto centro, double r){ this.centro = centro; this.raggio = raggio; } // metodo costruttore di default, costruisce // la circonferenza goniometrica Circonferenza( ){ centro = new Punto( ); raggio = 1; Punto centroA = new Punto(3,4); // Punto a = (3,4,0) Circonferenza cirA = new Circonferenza(centroA , 8); Circonferenza cirB = new Circonferenza( ); } } // fine classe ProvaCirconferenza L’oggetto centroA della classe Punto viene prima creato e poi passato come parametro attuale per costruire l’oggetto cirA della classe Circonferenza } } // fine classe Circonferenza I tipi semplici in java sono passati automaticamente per valore, cioè viene fatta una copia. Gli oggetti invece vengono passati automaticamente per riferimento. Questo vuol dire che se un oggetto viene passato come parametro ad un metodo che ne cambia le caratteristiche è l’oggetto stesso che viene cambiato. Vediamo un esempio: UD4: I metodi in java GLI OGGETTI SONO PASSATI AUTOMATICAMENTE PER RIFERIMENTO Esempio: //*************** file: ManipolaPunti.java //*************** file: ProvaManipola.java public class ManipolaPunti { public class ProvaManipola { // metodo static che sposta il punto passato come // parametro di un quantita’ s public static void main ( String args[ ] ) { Punto p = new Punto(3,4); public static void sposta (Punto p, double s ){ p.x = p.x + s; p.y = p.y + s; p.z = p.z + s; } } // fine classe ManipolaPunti // Punto p =(3,4,0) // l’oggetto p viene passato come parametro attuale ManipolaPunti.sposta (p,2); System.out.println(“x = “ + p.x ); System.out.println(“y = “ + p.y ); System.out.println(“z = “ + p.z ); } } // fine classe ProvaManipola L’output di questo programma sarà: x=5 y=6 z=2 UD4: I metodi in java Come si vede dall’output, le coordinate di p sono cambiate. Ricorda che: anche le stringhe e gli array in Java sono oggetti e quindi vengono passati automaticamente per riferimento. EREDITARIETA’ Java supporta il meccanismo dell’ereditarietà. E’ possibile specificare una sola superclasse per qualunque sottoclasse creata. E’ possibile creare una gerarchia di ereditarietà in cui una sottoclasse diventa superclasse di un’altra sottoclasse. GERARCHIA DI EREDITARIETA' Rettangolo ____________ base altezza Parallelepipedo ___________ Rett_colorato ___________ larghezza colore Scatolo ____________ peso EREDITARIETA’ Una sottoclasse può accedere a tutti i membri della superclasse: variabili di istanza e metodi, che sono stati dichiarati come public o protected, ma non come private. Esempio: Estendiamo la classe Rettangolo con la classe Parallelepipedo. //*************** file: Rettangolo.java public class Rettangolo { double base; double altezza; // var di istanza // var di istanza //----- metodo costruttore----Rettangolo( double base, double altezza) { this.base = base; this.altezza =altezza; } //----- metodo cambiadim ----void cambiadim( int scalare) { base = base * scalare; altezza =altezza * scalare; } } // fine classe Rettangolo UD4: I metodi in java //*************** file: Parallelepipedo.java public class Parallelepipedo extends Rettangolo{ double larghezza; //variabile di istanza //---- metodo costruttore con 3 parametri -----------Parallelepipedo( double b, double a, double l ){ base =b; altezza = a; larghezza =l; } //--------- metodo costruttore con 1 parametro ------// costruisce il cubo Parallelepipedo( double lato ){ base = lato; altezza = lato; larghezza =lato; } } // fine classe Parallelepipedo UTILIZZO DI SUPER PER CHIAMARE I COSTRUTTORI DELLA SUPERCLASSE Supponiamo di voler dichiarare come private nella classe Rettangolo le variabili di istanza base e altezza, allora esse non saranno più accessibili dalla classe estesa Parallelepipedo, e non potranno più essere usate neanche dal metodo costruttore. Java fornisce un sistema per utilizzare il metodo costruttore della classe immediatamente sopra. //*************** file: Rettangolo.java public class Rettangolo { double base; // var di istanza double altezza; // var di istanza //----- metodo costruttore con 2 parametri Rettangolo( double b, double a) { base = b; altezza =a; } //----- metodo costruttore con 1 parametro // costruisce il quadrato ---Rettangolo( double lato) { base = lato; altezza = lato; } //----- metodo cambiadim ----void cambiadim( int scalare) { base = base * scalare; altezza =altezza * scalare; } } // fine classe Rettangolo UD4: I metodi in java //*************** file: Parallelepipedo.java public class Parallelepipedo extends Rettangolo { private double larghezza; //variabile di istanza //---- metodo costruttore con 3 parametri Parallelepipedo( double b, double a, double l ){ super( b, a ); larghezza =l; } //--- metodo costruttore con 2 parametri -----Parallelepipedo( double lato, double l ){ super( lato ); larghezza =l; } //---- metodo costruttore con 1 parametro -----// costruisce il cubo Parallelepipedo( double lato ){ super( lato ); larghezza =lato; } } // fine classe Parallelepipedo UTILIZZO DEI METODI DELLA CLASSE SUPERIORE Il metodo cambiadim nella classe Rettangolo può essere richiamato anche da un oggetto della classe parallelepipedo. //*************** file: ProvaParallelepipedo.java public class ProvaParallelepipedo { public static void main ( String args[ ]) { //posso creare oggetti con i diversi metodi costruttori Parallelepipedo p1 = new Parallelepipedo(3,4,5); L’output di questo programma sarà: Dimensioni dell’oggetto cubo: base = 6 altezza = 6 larghezza = 3 // creo l’oggetto cubo di lato 3 Parallelepipedo cubo = new Parallelepipedo( 3 ); //applico ora il metodo cambiadim della classe superiore //Rettangolo cubo.cambiadim( 2 ); // Attenzione per poter accedere in questo modo alle variabili // di istanza, esse devono essere dichiarate come public System.out.println(“Dimensioni dell’oggetto cubo: “); System.out.println(“base = “ + cubo.base); System.out.println(“altezza = “ + cubo.altezza); System.out.println(“larghezza = “ + cubo.larghezza ); } } // Fine classe ProvaParallelepipedo UD4: I metodi in java OSSERVA CHE: sono state modificate solo la base e l’altezza quindi l’oggetto cubo non è più un cubo. UNA ALTERNATIVA AL SUPER UN OGGETTO DELLA SUPERCLASSE PUO’ ESSERE DICHIARATO COME VARIABILE DI ISTANZA NELLA SOTTOCLASSE E PUO’ ESSERE PASSATO COME PARAMETRO NEI METODI COSTRUTTORI DELLA SOTTOCLASSE //*************** file: ParallelepipA..java public class ParallelepipA extends Rettangolo { Rettangolo r; // variabile di istanza double larghezza; // variabile di istanza //---- metodo costruttore con 3 parametri ParallelepipA( double b, double a, double l ){ r = new Rettangolo(b,a); larghezza =l; } //--- metodo costruttore con 2 parametri -----ParallelepipA( Rettangolo r1, double l ){ r = r1; larghezza =l; } //---- metodo costruttore con 1 parametro -----// costruisce il cubo ParallelepipA( double lato ){ r = new Rettangolo( lato ); larghezza =lato; } } // fine classe ParallelepipA UD4: I metodi in java Nel riquadro accanto nota che: Invece di ridichiarare la variabili base e altezza nella sottoclasse, dichiaro direttamente un oggetto Rettangolo come variabile di istanza. Il metodo costruttore con 2 parametri ha come parametro un oggetto della superclasse Rettangolo. //*************** file: ProvaParallelepipA.java public class ProvaParallelepipA { public static void main ( String args[ ]) { //istanziazione a partire dai 3 lati. ParallelepipA p1 = new ParallelepipA (3,4,5); // creo un oggetto r della classe Rettangolo Rettangolo r = new rettangolo(1,2); // e poi lo utilizzo nella costruzione di un oggetto della //classe Parallelepipedo ParallelepipA p2 = new ParallelepipA( r , 5 ); } } // Fine classe ProvaParallelepipA _________________________________________ Per istanziare il ParallelepipA p2 abbiamo usato un oggetto della classe Rettangolo e la misura della larghezza. RIDEFINIZIONE DEI METODI (OVERRIDE) Come si è visto negli esempi precedenti, quando si estende una classe può essere utile poter adeguare dei metodi alla struttura della classe estesa. Java permette di ridefinire i metodi. Questa è un’altra maniera in cui viene realizzato il polimorfismo. In una gerarchia di classi, quando un metodo di una sottoclasse ha lo stesso nome e lo stesso tipo di ritorno di un metodo della superclasse , si dice che il metodo nella sottoclasse ridefinisce (override) il metodo della superclasse. Quando un metodo ridefinito viene chiamato all’interno di una sottoclasse fa sempre riferimento alla versione ridefinita nella sottoclasse, il metodo della superclasse viene nascosto. I metodi ridefiniti consentono a Java di supportare il polimorfismo run-time (durante l’esecuzione). La capacità di richiamare metodi su istanze di nuove classi senza dove ricompilare è uno strumento di grande potenza. UD4: I metodi in java RIDEFINIZIONE DEI METODI Esempio: estendiamo la classe Rettangolo con la sottoclasse Parallelepipedo e ridefiniamo il metodo cambiadim in modo che cambi le dimensioni senza deformare il parallelepipedo. //*************** file: Parallelepipedo.java public class Parallelepipedo extends Rettangolo { double larghezza; //variabile di istanza //metodo costruttore con 3 parametri Parallelepipedo( double b, double a, double l ){ super( b, a ); larghezza =l; } //metodo costruttore con 1 parametro, //costruisce il cubo Parallelepipedo( double lato ){ super( lato ); larghezza =lato; } //ridefinizione del metodo cambiadim void cambiadim( int scalare) { base = base * scalare; altezza =altezza * scalare; larghezza = larghezza * scalare; } } // fine classe Parallepipedo //*************** file: ProvaParallelepipedo.java public class ProvaParallelepipedo { public static void main ( String args[ ]) { // creo l’oggetto cubo di lato 3 Parallelepipedo cubo = new Parallelepipedo( 3 ); //applico ora il metodo cambiadim, verrà automaticamente //richiamato il metodo ridefinito nella sottoclasse cubo.cambiadim( 2 ); System.out.println(“Dimensioni dell’oggetto cubo: “); System.out.println(“base = “ + cubo.base); System.out.println(“altezza = “ + cubo.altezza); System.out.println(“larghezza = “ + cubo.larghezza ); } } // fine classe ProvaParallepipedo _______________________________________________ L’output di questo programma sarà: Dimensioni dell’oggetto cubo: base = 6 altezza = 6 larghezza = 6 Il nostro cubo si è ingrandito ma non è stato deformato UD4: I metodi in java CLASSI ASTRATTE E METODI ASTRATTI A volte si può desiderare definire una superclasse che dichiari una struttura astratta senza entrare nei dettagli dell’implementazione. Figura colore dim1 area( ) perimetro( ) intestazione( ) {...} area ( ) {...} perimetro( ) {...} Cerchio UD4: I metodi in java dim2 dim3 area( ) {...} perimetro( ) {...} Triangolo dim2 area( ) {...} perimetro( ) {...} Rettangolo CLASSI ASTRATTE E METODI ASTRATTI E’ possibile anche che dei metodi non abbiano significato se non sono ridefiniti nelle sottoclassi. La soluzione che offre Java è il metodo astratto. //*************** file: Figura.java Notare che: abstract class Figura{ String colore; double dim1; // variabile di istanza //variabile di istanza //------------- metodo costruttore concreto -----Figura(String color, double d){ colore = new String( color ); dim1 = d; } //--------------- metodo astratto ----------------------abstract double area( ) ; //--------------- metodo astratto ----------------------abstract double perimetro( ) ; //--------------- metodo concreto --------------------void intestazione{ system.out.println(“Questa è una figura geometrica”); } } // fine classe Figura UD4: I metodi in java I metodi concreti sono permessi nelle classi astratte. Nei metodi astratti non è presente nessun corpo del metodo. Le sottoclassi sono obbligate a ridefinire tutti i metodi astratti della superclasse. SOTTOCLASSI DELLE CLASSI ASTRATTE Definiamo le classi FigCerchio e FigRettangolo come sottoclassi della classe astratta Figura //*************** file: FigCerchio.java //*************** file: FigRettangolo.java public class FigCerchio extends Figura{ public class FigRettangolo extends Figura { //metodo costruttore FigCerchio( String color, double raggio) { super (color, raggio); } //ridefinizione del metodo area: obbligatoria double area( ) { return( dim1 * dim1 * 3.14 ); } //ridefinizione del metodo perimetro: obbligatoria double perimetro( ) { return( 2 * dim1 * 3.14 ); } } // fine classe FigCerchio _______________________________________ Nota che: il metodo perimetro va comunque ridefinito nonostante il nome più appropriato sia circonferenza. UD4: I metodi in java double dim2; // variabile di istanza //metodo costruttore FigRettangolo( String col, double d1,double d2) { super (col, d1); dim2= d2; } //ridefinizione del metodo area: obbligatoria double area( ) { return( dim1 * dim2); } //ridefinizione del metodo perimetro: obbligatoria double perimetro( ) { return( 2 * (dim1 + dim2)); } } // fine classe FigRettangolo ISTANZIAZIONE DI OGGETTI CON LE CLASSI ASTRATTE Le classi astratti non possono essere utilizzate per istanziare oggetti, però è possibile creare un riferimento della classe astratta ad un oggetto della sottoclasse. Vediamo come: //*************** file: ProvaFigura.java public class ProvaFigura { public static void main ( String args[ ]) { //Questo comando è illegale infatti è lasciato come commento //Figura F = new Figura(“Rosso”, 5); // posso invece creare un oggetto della sottoclasse FigCerchio FigCerchio c = new FigCerchio(“Rosso”, 5); //questa istruzione è ammessa, non sto creando nessun oggetto // ma una variabile di riferimento di tipo Figura Figura f1; // a questo punto è possibile assegnare l’oggetto di tipo FigCerchio // alla variabile di tipo Figura f1 = c; // posso ora richiamare i metodi sulla variabile di tipo figura // ATTENZIONE: f1e’ un riferimento, quindi tutte le modifiche su f1 si ripercuoteranno su c. system.out.println(“L’area e’ ” + f1.area( ) ); } } // fine classe ProvaFigura UD4: I metodi in java FINE UD4: I metodi in java