• Non ci sono risultati.

15 - Ereditariet`a Programmazione e analisi di dati Modulo A: Programmazione in Java Paolo Milazzo

N/A
N/A
Protected

Academic year: 2022

Condividi "15 - Ereditariet`a Programmazione e analisi di dati Modulo A: Programmazione in Java Paolo Milazzo"

Copied!
23
0
0

Testo completo

(1)

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. 2018/2019

(2)

Classi simili...

A volte in uno stesso programma ci sono classi che descrivono cose simili tra loro.

Esempio:

supponiamo di voler realizzare un programma per la gestione degli insegnamenti di un corso di laurea

per ogni insegnamento vogliamo sapere chi ` e il docente responsabile e chi sono gli studenti frequentanti

per descrivere docenti e studenti ci servono due classi: Professore e

Studente

(3)

Partiamo con la classe Studente

p u b l i c c l a s s S t u d e n t e {

p r i v a t e S t r i n g n o m e ; // n o m e e c o g n o m e p r i v a t e S t r i n g i n d i r i z z o ; // i n d i r i z z o

p r i v a t e int m a t r i c o l a ; // n u m e r o di m a t r i c o l a p r i v a t e int a n n o ; // a n n o di f r e q u e n t a z i o n e

p r i v a t e s t a t i c int u l t i m a M a t r i c o l a = 0 // v a r i a b i l e s t a t i c a // c o s t r u t t o r e

p u b l i c S t u d e n t e ( S t r i n g nome , S t r i n g i n d i r i z z o ) { t h i s. n o m e = n o m e ;

t h i s. i n d i r i z z o = i n d i r i z z o ;

// g e n e r a la m a t r i c o l a u s a n d o la v a r i a b i l e s t a t i c a t h i s. m a t r i c o l a = u l t i m a M a t r i c o l a + 1;

u l t i m a M a t r i c o l a ++;

// si a s s u m e che un n u o v o s t u d e n t e sia al p r i m o a n n o t h i s. a n n o = 1;

} ( s e g u e )

(4)

Studenti e professori (2)

( s e g u e S t u d e n t e )

// f o r n i s c e il n o m e d e l l o s t u d e n t e p u b l i c S t r i n g g e t N o m e () { r e t u r n n o m e ; } // f o r n i s c e l ’ i n d i r i z z o d e l l o s t u d e n t e

p u b l i c S t r i n g g e t I n d i r i z z o () { r e t u r n i n d i r i z z o ; } // c o n s e n t e di m o d i f i c a r e l ’ i n d i r i z z o

p u b l i c v o i d s e t I n d i r i z z o ( S t r i n g i n d i r i z z o ) { t h i s. i n d i r i z z o = i n d i r i z z o ;

}

// f o r n i s c e la m a t r i c o l a

p u b l i c int g e t M a t r i c o l a () { r e t u r n m a t r i c o l a ; } // f o r n i s c e l ’ a n n o di f r e q u e n t a z i o n e

p u b l i c int g e t A n n o () { r e t u r n a n n o ; } ( s e g u e )

(5)

( s e g u e S t u d e n t e )

// m o d i f i c a l ’ a n n o di f r e q u e n t a z i o n e p u b l i c v o i d s e t A n n o (int a n n o ) {

if ( anno >0) t h i s. a n n o = a n n o ; }

// v e r i f i c a se lo s t u d e n t e e ’ f u o r i c o r s o

p u b l i c b o o l e a n i s F u o r i c o r s o () { r e t u r n ( anno > 5 ) ; }

// s t a m p a le i n f o r m a z i o n i s u l l o s t u d e n t e p u b l i c v o i d v i s u a l i z z a () {

S y s t e m . out . p r i n t l n (" N o m e : " + n o m e );

S y s t e m . out . p r i n t l n (" I n d i r i z z o : " + i n d i r i z z o );

S y s t e m . out . p r i n t l n (" M a t r i c o l a : " + m a t r i c o l a );

S y s t e m . out . p r i n t l n (" A n n o : " + a n n o );

if ( i s F u o r i c o r s o ())

S y s t e m . out . p r i n t l n (" ( S t u d e n t e f u o r i c o r s o ) ");

e l s e

S y s t e m . out . p r i n t l n (" ( S t u d e n t e in c o r s o ) ");

S y s t e m . out . p r i n t l n ();

} }

(6)

Studenti e professori (4)

Ora ` e la volta della classe Professore

p u b l i c c l a s s P r o f e s s o r e {

p r i v a t e S t r i n g n o m e ; // n o m e e c o g n o m e p r i v a t e S t r i n g i n d i r i z z o ; // i n d i r i z z o

p r i v a t e S t r i n g c o d i c e D o c e n t e ; // c o d i c e del d o c e n t e p r i v a t e S t r i n g d i p a r t i m e n t o ; // d i p a r t . di a f f e r e n z a // c o s t r u t t o r e

p u b l i c P r o f e s s o r e ( S t r i n g nome , S t r i n g i n d i r i z z o , S t r i n g c o d i c e D o c e n t e ,

S t r i n g d i p a r t i m e n t o ) { t h i s. n o m e = n o m e ;

t h i s. i n d i r i z z o = i n d i r i z z o ;

t h i s. c o d i c e D o c e n t e = c o d i c e D o c e n t e ; t h i s. d i p a r t i m e n t o = d i p a r t i m e n t o ; }

( s e g u e )

(7)

( s e g u e P r o f e s s o r e )

// f o r n i s c e il n o m e del p r o f e s s o r e p u b l i c S t r i n g g e t N o m e () { r e t u r n n o m e ; } // f o r n i s c e l ’ i n d i r i z z o del p r o f e s s o r e

p u b l i c S t r i n g g e t I n d i r i z z o () { r e t u r n i n d i r i z z o ; } // c o n s e n t e di m o d i f i c a r e l ’ i n d i r i z z o

p u b l i c v o i d s e t I n d i r i z z o ( S t r i n g i n d i r i z z o ) { t h i s. i n d i r i z z o = i n d i r i z z o ;

} ( s e g u e )

(8)

Studenti e professori (6)

( s e g u e P r o f e s s o r e )

// f o r n i s c e il c o d i c e d o c e n t e p u b l i c S t r i n g g e t C o d i c e D o c e n t e () {

r e t u r n c o d i c e D o c e n t e ; }

// f o r n i s c e il d i p a r t i m e n t o p u b l i c S t r i n g g e t D i p a r t i m e n t o () {

r e t u r n d i p a r t i m e n t o ; }

// s t a m p a le i n f o r m a z i o n i sul p r o f e s s o r e p u b l i c v o i d v i s u a l i z z a () {

S y s t e m . out . p r i n t l n (" N o m e : P r o f . " + n o m e );

S y s t e m . out . p r i n t l n (" I n d i r i z z o : " + i n d i r i z z o );

S y s t e m . out . p r i n t l n (" C o d i c e : " + c o d i c e D o c e n t e );

S y s t e m . out . p r i n t l n (" D i p a r t i m e n t o : " + d i p a r t i m e n t o );

S y s t e m . out . p r i n t l n ();

} }

(9)

Tutto OK.... ma quanto codice Java ripetuto...

Studente e Professore hanno diverse cose in comune:

due variabili d’istanza: nome e indirizzo

alcuni metodi: getNome(), getIndirizzo() e setIndirizzo() Questi membri in effetti non descrivono caratteristiche specifiche degli studenti e dei professori

sono caratteristiche comuni di tutte le persone

Isoliamo dunque i membri condivisi di Studente e Professore in una nuova classe Persona

aggiungiamo anche un costruttore e un metodo visualizza()

(10)

Persone

Ecco la classe Persona

p u b l i c c l a s s P e r s o n a {

p r i v a t e S t r i n g n o m e ; // n o m e e c o g n o m e p r i v a t e S t r i n g i n d i r i z z o ; // i n d i r i z z o // c o s t r u t t o r e

p u b l i c P e r s o n a ( S t r i n g nome , S t r i n g i n d i r i z z o ) { t h i s. n o m e = n o m e ;

t h i s. i n d i r i z z o = i n d i r i z z o ; }

p u b l i c S t r i n g g e t N o m e () { r e t u r n n o m e ; }

p u b l i c S t r i n g g e t I n d i r i z z o () { r e t u r n i n d i r i z z o ; } p u b l i c v o i d s e t I n d i r i z z o ( S t r i n g i n d i r i z z o ) {

t h i s. i n d i r i z z o = i n d i r i z z o ; }

// v i s u a l i z z a i d a t i d e l l a p e r s o n a p u b l i c v o i d v i s u a l i z z a () {

S y s t e m . out . p r i n t l n (" N o m e : " + n o m e );

S y s t e m . out . p r i n t l n (" I n d i r i z z o : " + i n d i r i z z o );

S y s t e m . out . p r i n t l n ();

} }

(11)

Ci` o che si pu` o fare ora ` e ridefinire le classi Studente e Professore come estensioni della classe Persona

Le classi Studente e Professore erediteranno cos`ı i membri di Persona (senza doverli definire di nuovo)

tali membri saranno quindi definiti una volta sola (in Persona) Per definire una classe come estensione di un’altra si deve usare la primitiva extends

deve essere usata all’inizio della definizione della classe

p u b l i c c l a s s S t u d e n t e e x t e n d s P e r s o n a { ...

}

(12)

Estensione di una classe (2)

Terminologia:

La classe che viene estesa (es. Persona) ` e detta superclasse

La classe che estende (es. Studente) ` e detta sottoclasse

Questa terminologia ` e legata al fatto che solitamente la relazione di

estensione viene rappresentata cos`ı (superclasse sopra, sottoclassi sotto):

(13)

Cosa succede quando si crea un oggetto di una classe che ne estende un’altra?

p u b l i c c l a s s S t u d e n t e e x t e n d s P e r s o n a { ...

}

Altrove:

...

S t u d e n t e s = new S t u d e n t e ();

...

(14)

Estensione di una classe (4)

La creazione di un oggetto di una sottoclasse (es. Studente) segue i seguenti passi:

1. Viene creato un oggetto della superclasse (es. Persona)

I

tramite il costruttore di default (Persona())

I

oppure, tramite un altro costruttore richiamato esplicitamente tramite il riferimento super (simile a this...)

2. Vengono aggiunte all’oggetto le variabili della sottoclasse

3. Viene eseguito il costruttore della sottoclasse (es. Studente)

(15)

Il risultato della creazione (nella memoria Heap) di un oggetto di una

sottoclasse ` e quindi il seguente:

(16)

Nuove versioni di Studente e Professore (1)

Ridefiniamo la classe Studente

p u b l i c c l a s s S t u d e n t e e x t e n d s P e r s o n a {

p r i v a t e int m a t r i c o l a ; // n u m e r o di m a t r i c o l a p r i v a t e int a n n o ; // a n n o di f r e q u e n t a z i o n e p r i v a t e s t a t i c int U l t i m a M a t r i c o l a = 0;

// c o s t r u t t o r e ( u g u a l e a p r i m a )

p u b l i c S t u d e n t e ( S t r i n g nome , S t r i n g i n d i r i z z o ) { // c h i a m a il c o s t r u t t o r e di P e r s o n a

s u p e r( nome , i n d i r i z z o );

// i n i z i a l i z z a le a l t r e v a r i a b i l i t h i s. m a t r i c o l a = u l t i m a M a t r i c o l a + 1;

u l t i m a M a t r i c o l a ++;

t h i s. a n n o = 1;

} ( s e g u e ) }

(17)

super ` e un riferimento all’oggetto stesso (come this) ma che consente di utilizzare i costruttori e i metodi della superclasse

Ad esempio, dentro a Studente:

this(...) richiama un costruttore della classe Studente super(...) richiama un costruttore della classe Persona

NOTA: Come this(...) anche super(...) deve essere eseguito come primo comando di un costruttore.

In caso la chiamata super(...) sia omessa, viene invocato automaticamente il costruttore senza parametri della superclasse Quindi, nel costruttore della sottoclasse la chiamata super(....) pu` o essere omessa solo se:

la superclasse prevede un costruttore senza parametri (es. il

(18)

Nuove versioni di Studente e Professore (3)

( s e g u e S t u d e n t e )

p u b l i c int g e t M a t r i c o l a () { r e t u r n m a t r i c o l a ; } p u b l i c int g e t A n n o () { r e t u r n a n n o ; }

p u b l i c v o i d s e t A n n o (int a n n o ) { if ( anno >0) t h i s. a n n o = a n n o ; }

p u b l i c b o o l e a n i s F u o r i c o r s o () { r e t u r n ( anno > 5 ) ; } // s t a m p a le i n f o r m a z i o n i s u l l o s t u d e n t e

// N O T A : per r e c u p e r a r e n o m e e i n d i r i z z o d e v e u s a r e // i m e t o d i p u b b l i c i di P e r s o n a !

p u b l i c v o i d v i s u a l i z z a () {

S y s t e m . out . p r i n t l n (" N o m e : " + g e t N o m e ( ) ) ; S y s t e m . out . p r i n t l n (" I n d i r i z z o : " + g e t I n d i r i z z o ( ) ) ; S y s t e m . out . p r i n t l n (" M a t r i c o l a : " + m a t r i c o l a );

S y s t e m . out . p r i n t l n (" A n n o : " + a n n o );

if ( i s F u o r i c o r s o ())

S y s t e m . out . p r i n t l n (" ( S t u d e n t e f u o r i c o r s o ) ");

e l s e

S y s t e m . out . p r i n t l n (" ( S t u d e n t e in c o r s o ) ");

S y s t e m . out . p r i n t l n ();

} }

(19)

Il metodo visualizza() di Studente richiede due osservazioni

OSSERVAZIONE 1: nome e indirizzo sono variabili private di Persona Il fatto che Studente sia sottoclasse di Persona non la autorizza ad accedere alle variabili private...

CONSEGUENZE:

devo usare i metodi pubblici (se disponibili, come in questo caso) altrimenti dovrei cambiare il modificatore di visibilt` a di nome e indirizzo in Persona

I

Ma quale devo usare???

(20)

Nuove versioni di Studente e Professore (5)

Rivediamoli ancora una volta:

private Utilizzabile solo all’interno della stessa classe senza modificatore Utilizzabile solo nel package che contiene la classe

protected Utilizzabile nel package che contiene la classe, e in tutte le classi che ereditano da essa public Utilizzabile ovunque

Visto che non ho definito packages (quindi uso il package default) i casi

“senza modificatore”, protected e public sono di fatto equivalenti Ergo, se non voglio rendere completamente pubbliche le variabili di Persona devo inserire le mie classi in un package:

I

Ometter` o il modificatore per limitare la visibilt` a alle sole classi del package

I

oppure user` o protected per estendere la visibilit` a anche a sottoclassi

di Persona in altri packages

(21)

OSSERVAZIONE 2: visualizza() era gi` a stato definito in Persona Questo ` e un caso di overriding di un metodo

La sottoclasse ridefinisce (sostituendolo) un metodo della superclasse Per ottenere l’overriding di un metodo ` e necessario che la firma del metodo nella sottoclasse sia identica a quella del metodo nella superclasse!

in caso contrario avremmo overloading: entrambi i metodi (il vecchio e il nuovo) sarebbero abilitati ed eseguiti in base alla firma

ATTENZIONE: overloading e overriding di metodi sono due cose diverse:

l’overloading ` e un meccanismo che consente di avere pi` u metodi con lo stesso nome

l’overriding ` e un meccanismo che consente di sostituire un metodo di

una superclasse

(22)

Nuove versioni di Studente e Professore (7)

Ridefiniamo anche la classe Professore

p u b l i c c l a s s P r o f e s s o r e e x t e n d s P e r s o n a { p r i v a t e S t r i n g c o d i c e D o c e n t e ;

p r i v a t e S t r i n g d i p a r t i m e n t o ;

p u b l i c P r o f e s s o r e ( S t r i n g nome , S t r i n g i n d i r i z z o , S t r i n g c o d i c e D o c e n t e ,

S t r i n g d i p a r t i m e n t o ) { s u p e r( nome , i n d i r i z z o );

t h i s. c o d i c e D o c e n t e = c o d i c e D o c e n t e ; t h i s. d i p a r t i m e n t o = d i p a r t i m e n t o ; }

p u b l i c S t r i n g g e t C o d i c e D o c e n t e () { r e t u r n c o d i c e D o c e n t e ; } p u b l i c S t r i n g g e t D i p a r t i m e n t o () { r e t u r n d i p a r t i m e n t o ; } p u b l i c v o i d v i s u a l i z z a () {

S y s t e m . out . p r i n t l n (" N o m e : P r o f . " + g e t N o m e ( ) ) ; S y s t e m . out . p r i n t l n (" I n d i r i z z o : " + g e t I n d i r i z z o ( ) ) ; S y s t e m . out . p r i n t l n (" C o d i c e : " + c o d i c e D o c e n t e );

S y s t e m . out . p r i n t l n (" D i p a r t i m e n t o : " + d i p a r t i m e n t o );

S y s t e m . out . p r i n t l n ();

} }

(23)

Per concludere, un main:

p u b l i c c l a s s U s a S t u d e n t e P r o f e s s o r e { 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 ) {

P e r s o n a x = new P e r s o n a (" G i n o "," Via M i l a n o 10 ");

x . v i s u a l i z z a ();

S t u d e n t e s1 = new S t u d e n t e (" C a r l o B i a n c h i "," Via G a r i b a l d i 71 ");

s1 . v i s u a l i z z a ();

S t u d e n t e s2 = new S t u d e n t e (" M a r i o R o s s i "," Via M a z z i n i 11 ");

s2 . v i s u a l i z z a ();

P r o f e s s o r e p1 = new P r o f e s s o r e (" M a r i o R o s s i ",

" Via M a r c o n i 10 ", " a 1 1 2 3 ",

" D i p a r t i m e n t o di I n f o r m a t i c a ");

p1 . v i s u a l i z z a ();

P r o f e s s o r e p2 = new P r o f e s s o r e (" L u i g i V e r d i ",

" Via V e r d i 70 "," a 9 5 2 1 ",

" D i p a r t i m e n t o di B i o l o g i a ");

p2 . v i s u a l i z z a ();

}

Riferimenti

Documenti correlati

Ogni area della schermata principale di Eclipse ` e detta Vista (View) La vista centrale ci consentira di scrivere il nostro programma La vista “Package Explorer” (a sinistra)

In Java, l’Input/Output su file segue il modello degli stream (o flussi) Uno stream di input prevede una sorgente di dati (es. un file) che possono essere utilizzati da un

Nella dichiarazione di una variabile se ne specifica il nome e il tipo (o meglio, il tipo dei valori che pu` o contenere). Nell’esempio, abbiamo dichiarato tre variabili con nomi

cpa timing live-person cpa timing timeout cpa timing term-tone cpa timing silent cpa timing valid-speech cpa timing noise-period cpa threshold active-signal cpa threshold

La guardia pu` o essere una qualunque espressione booleana Il comando (o blocco) ` e detto corpo del do-while. Semantica

Il numero di figli di ogni nodo di un albero pu` o essere fiassato o variabile Quando il numero dei figli di ogni nodo ` e fissato a 2, l’albero si dice binario (come

AUTOCERTIFICAZIONE DEL COSTRUTTORE. (ai sensi

Nelle città grandi inv ece, o ve la lunghezza rimar- c hevole d elle vi e longitudinali e trasv ersali e l'im- portanza del transito di pedoni, animali, v ettur e e carri d'ogni m