La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Cose nuove di Java (prima a chiacchiera, poi formalmente)

Presentazioni simili


Presentazione sul tema: "Cose nuove di Java (prima a chiacchiera, poi formalmente)"— Transcript della presentazione:

1 Cose nuove di Java (prima a chiacchiera, poi formalmente)

2 Ruolo delle classi in Java I programmi in Java consistono di classi. Le classi consentono di definire: collezioni di procedure (metodi statici) prototipi di oggetti (tramite variabili e metodi d’istanza, che definiscono il loro stato interno e le operazioni) Le due funzionalità possono coesistere all’interno di una stessa classe

3 Esempio Una classe che definisce una collezione di procedure public class Num { public static int gcd (int n, int d) { while (n != d) if (n > d) n = n - d; else d = d - n; return n;} public static boolean isPrime (int p) { // implementazione} }

4 Ricordiamo che…… Variabili e metodi statici appartengono alla classe Variabili e metodi di istanza appartengono agli oggetti (istanze della classe) Una classe definisce un tipo (nome della classe) Gli oggetti istanza della classe hanno quel tipo

5 Nel contesto del paradigma di programmazione orientato ad oggetti, l’ereditarietà è un meccanismo fondamentale sia per il riutilizzo del codice che per lo sviluppo incrementale di programmi. Questo meccanismo permette infatti di estendere e potenziare classi già esistenti, e di fattorizzare informazioni comuni a più classi Ereditarietà 1

6 In molti casi occorre definire una classe i cui oggetti hanno una struttura più ricca di quella di una classe già definita, oppure che realizza delle funzionalità aggiuntive In questi casi si può definire la nuova classe come sottoclasse della precedente, ereditando le caratteristiche già presenti Ereditarietà 2

7 class Persona { String nome; String indirizzo; public Persona() {this.nome = ""; this.indirizzo = ""; } public Persona(String nome,String indirizzo) {this.nome = nome; this.indirizzo = indirizzo; } public String getNome() {return nome; } Esempio di classe 1

8 public String getIndirizzo() {return indirizzo; } public void visualizza() {System.out.println("Nome: " + nome + "\nIndirizzo: " + indirizzo); } public boolean omonimo(Persona p) {return this.nome.equals IgnoreCase(p.nome); } Esempio di classe 2

9 Vogliamo definire una classe Studente che rappresenti gli studenti iscritti ad un corso di laurea. Ogni studente è descritto dal nome, dall’indirizzo, dal numero di matricola e dal piano di studio. Uno Studente è un tipo particolare di Persona. L’ereditarietà ci consente di definire questa classe senza ripetere la descrizione di tutte le variabili e i metodi di Persona, ma in modo incrementale, come sottoclasse. Esempio di sottoclasse 1

10 class Studente extends Persona { int matricola; String pianoDiStudio; static int nextMatricola = 1; public Studente() { nextMatricola ++; this.matricola = nextMatricola; this.pianoDiStudio = ""; } public Studente(String nome, String indirizzo) { this.nome = nome; this.indirizzo = indirizzo; nextMatricola ++; this.matricola = nextMatricola; this.pianoDiStudio = ""; } Esempio di sottoclasse 2

11 public String getPdS() {return pianoDiStudio; } public void modificaPdS(String nuovoPdS) { pianoDiStudio += nuovoPdS + "\n"; } Esempio di sottoclasse 3

12 La parola chiave extends significa che Studente è una sottoclasse o classe derivata di Persona Persona è una superclasse o classe genitrice di Studente Un’istanza di Studente avrà quattro variabili di istanza: * nome e indirizzo ereditate da Persona * matricola e pianoDiStudio definite nella sottoclasse Studente Analogamente, su di essa possono essere invocati i metodi d’istanza della sottoclasse ed anche quelli della superclasse.

13 Esempio di sottoclasse 4

14 Gerarchia di Tipi La relazione di sottoclasse è transitiva Si crea una gerarchia di classi (o di tipi) al cui top c’è la classe Object

15 Se c1 è una sottoclasse di (estende) c2 le variabili e metodi statici di c2 (e delle sue superclassi) sono visibili direttamente da c1 variabili e metodi di istanza di c2 (e delle sue superclassi) diventano anche variabili e metodi di istanza di c1 a meno di overriding Semantica informale

16 Una sottoclasse può riscrivere un metodo della superclasse (stesso nome, stessi parametri, stesso tipo) In tal caso sugli oggetti della sottoclasse viene utilizzato il metodo riscritto (quello più specifico) Overriding

17 Ad esempio, se invochiamo il metodo visualizza su un’istanza di Studente, verranno stampati solo i valori delle prime due variabili d’istanza (nome e indirizzo). public void visualizza() {System.out.println("Nome: " + nome + "\nIndirizzo: " + indirizzo); }

18 Se vogliamo stampare anche la matricola ed il piano di studio, possiamo sovrascrivere (override) visualizza aggiungendo a Studente il seguente metodo: public void visualizza() {System.out.println("Nome: " + nome + "\nIndirizzo: " + indirizzo); System.out.println("Matricola: " + matricola + "\nPianodiStudio: " + pianoDiStudio); }

19 Il comando p.visualizza() invocherà il metodo visualizza della classe Persona se p è un’istanza di Persona il nuovo metodo che stampa anche il numero di matricola e il piano di studio se p è un’istanza di Studente. La scelta del metodo più specifico non può essere fatta a tempo di compilazione (come vedremo a causa dei sottotipi)

20 Anche per i costruttori esiste un meccanismo di ereditarietà: se c è una classe che ha come superclassi (nell’ordine) le classi c1, c2, …., cn, all’atto della creazione di una istanza di c si eseguono automaticamente i costruttori di cn, …, c2, c1, c (nell’ordine). Costruttori

21 Esempio public Studente() { this.matricola = nextMatricola ++; this.pianoDiStudio = ""; } Il costruttore di Persona viene invocato automaticamente per inizializzare le variabili ereditate. public Persona() {this.nome = ""; this.indirizzo = ""; }

22 Grazie all’ereditarietà i sottotipi supportono il comportamento del supertipo, ovvero le istanze della sottoclasse hanno le variabili d’istanza ed i metodi (al limite overridden) del supertipo hanno accesso alle variabili ed ai metodi statici della superclasse Di conseguenza un oggetto del sottotipo può essere utilizzato dovunque sia richiesto un oggetto del supertipo. Principio di sostituzione 1

23 Un’istanza di Studente si può usare dovunque sia richiesto un oggetto di Persona, come in un assegnamento o nel passaggio di parametri. Persona tizio = new Studente("Mario Rossi", "Pisa"); /* corretto: su tizio posso invocare tutti i metodi di Persona, grazie all'ereditarieta' */ tizio.visualizza(); Studente pippo = new Studente("Pinco Pallino", "Empoli");... if(tizio.omonimo(pippo))... Esempio

24 Non è possibile il contrario, ovvero utilizzare un oggetto del supertipo al posto di uno del sottotipo. Il sottotipo può avere variabili e metodi (d’istanza o statici) aggiuntivi, per esempio il numero di matricola o il metodo che ritorna il piano di studio.... Studente tizio = new Persona("Mario Rossi", "Pisa"); /* errore di tipo*/ Attenzione:

25 Tipo apparente : tipo con cui una variabile è dichiarata Tipo effettivo: tipo del valore a cui la variabile si riferisce Il tipo apparente ed il tipo effettivo possono essere diversi, in particolare il tipo effettivo può essere un sottotipo del tipo apparente Persona tizio = new Studente("Mario Rossi", "Pisa");... Di conseguenza…..

26 Tipo Effettivo, Apparente, Controllo dei Tipi Java è fortemente tipato ossia il compilatore di Java verifica che ogni assegnamento e ogni chiamata di metodo siano corretti riguardo al tipo. le relazioni di subtyping permettono che una entità abbia un tipo effettivo diverso da quello apparente il tipo apparente è noto a tempo di compilazione il tipo effettivo è noto solo a tempo di esecuzione Il compilatore lavora solo col tipo apparente!

27 Esempio int y = 7; int z = 3; int x = Num.gcd (z,y); Num.gcd si apetta due interi e restituisce un intero. Perciò la chiamata e l’assegnamento sono corretti in base al tipo con cui le variabili sono dichiarate (tipo apparente).

28 Persona tizio = new Studente("Mario Rossi", "Pisa"); tizio.modificaPdS("Algebra"); Si verifica un errore di compilazione. Infatti abbiamo chiamato su tizio (variabile dichiarata di classe Persona ) un metodo della sottoclasse Studente. Anche se il tipo effettivo sarebbe giusto…… Esempio

29 In certe situazioni è utile/necessario invocare su di un identificatore un metodo di una sottoclasse. In questi casi si può usare l’operazione di cast Persona tizio = new Studente("Mario Rossi", "Pisa"); ((Studente)tizio).modificaPdS("Algebra"); In questo caso non ci sono errori in fase di compilazione, il compilatore verifica solo che il tipo apparente di tizio sia supertipo di Studente (tipo verso il quale facciamo il cast) e tratta nella chiamata di metodo tizio come se fosse del sottotipo Cast 1

30 Quando si valuta ((Studente) tizio) se tizio non ha tipo effettivo Studente, verrà sollevata una eccezione a run-time Si può controllare la classe di appartenenza di un oggetto prima del cast: if (tizio instanceof Studente) ((Studente) tizio).modificaPdS("Algebra"); La condizione (obj instanceof Classe) restituisce true se e solo se obj è una istanza della classe Classe. Cast 2

31 Cast, tipo effettivo, tipo apparente La scelta del metodo più specifico tra metodi overridden dipende dal tipo effettivo (scelta run-time) Il controllo dei tipi statico non evita errori di tipo run-time (a causa dei cast)

32 Se nella classe Persona avessimo dichiarato le variabili d’istanza private, il metodo visualizza di Studente avrebbe causato un errore in compilazione, tentando di accedere a variabili private dichiarate nella superclasse. public void visualizza() {System.out.println("Nome: " + nome + "\nIndirizzo: " + indirizzo); System.out.println("Matricola: " + matricola + "\nPianodiStudio: " + pianoDiStudio); } Visibilità dei nomi

33 Allora come avrebbe fatto un oggetto di tipo Studente a modificare le variabili d’istanza ereditate dalla superclasse? Si possono accedere le variabili attraverso i metodi della superclasse utilizzando super super (simile a this) fa riferimento all’istanza che sta eseguendo un metodo o un costruttore, ma costringe l’interprete a vedere l’oggetto come istanza della superclasse. Super 1

34 Riscriviamo il metodo visualizza per Studente in modo da chiamare il metodo visualizza di Persona per accedere alle variabili della superclasse public void visualizza() { super.visualizza(); System.out.println("Matricola: " + matricola + "\nPianodiStudio: " + pianoDiStudio); } Esempio


Scaricare ppt "Cose nuove di Java (prima a chiacchiera, poi formalmente)"

Presentazioni simili


Annunci Google