際際滷

際際滷Share a Scribd company logo
Java Ereditariet e Polimorfismo applicate in Java Davide Ficano [email_address]
Ereditariet Polimorfismo Abbiamo detto che Ereditariet significa avere un oggetto  base   con un insieme di stati e comportamenti presenti anche in oggetti derivati Polimorfismo significa assumere significati specifici in diversi contesti
Gerarchia oggetto Animale
Classe Base Animale public   class  Animale { private  String  nome ; public  Animale(String nuovoNome) { nome  = nuovoNome; } public  String getNome() { return   nome ; } public  String parla() { return   "Errore: Animale generico" ; } } Non stiamo descrivendo nessuna specie animale particolare quindi non sappiamo qual'竪 il verso * Notare che non esiste il metodo setNome(...) per fare in modo che una volta  dato il nome (nel costruttore) all'animale non lo si possa pi湛 cambiare
Classe specializzata Cane "extends" Animale public   class  Cane  extends  Animale { public  Cane(String nome)  {  super (nome);  } public  String parla() { return   "Ciao, io sono "  + getNome() +  " e faccio baubau" ; } } Viene usata la parola  extends  per derivare dalla classe Animale Il costruttore richiama quello della classe base tramite la parola riservata  super Il metodo  parla()  viene ridefinito.  Abbiamo applicato il Polimorfismo Viene richiamato il metodo  getNome  della classe base
Note su "extends" La parola riservata  extends  serve a derivare da una classe base Si pu嘆 derivare solo da una classe Avere l'ereditariet  singola  evita  le ambiguit dovute alla presenta dello stesso metodo in due classi base: quale chiamo? public   class  Cane  extends  Animale, Lassie { } La Sintassi 竪 sbagliata perch辿 extends accetta solo una classe
Costruttori ed ereditariet Esempio 1 I costruttori non vengono ereditati sono comunque accessibili tramite la sintassi  super (...) public   class  Cane  extends  Animale { ... ... } Non compila public   class  Cane  extends  Animale { public  Cane(String nome) { super (nome); } } La classe a sinistra non compila perch竪 non "vede" il costruttore della classe base La classe a destra dichiara un costruttore uguale a quello della classe base e poi lo richiama con la sintassi  super (...)
Utilizzo di super nei metodi /1 Anche i metodi possono richiamare  super  ma solo per riferirsi ad un metodo della classe base Significa che un metodo non pu嘆 richiamare un costruttore tramite  super public   class  Cane  extends  Animale { public  String parla() { super ( "fido" ); return  ...; } } Non compila, c'e' errore alla linea nr 3. un costruttore non puo' essere richiamato in un metodo Domanda: Perch辿 un costruttore non pu嘆 essere richiamato in un metodo?
Utilizzo di super nei metodi /2 E' utile usare super nei metodi quando si vuole richiamare il metodo con lo stesso nome presente nella classe base public   class  Cane  extends  Animale { public  String parla() { return   "Ciao, io sono "  +  super .parla() +  " e faccio baubau" ; } } Il metodo Cane.parla richiama il metodo Animale.parla la sintassi super.nomeMetodo pu嘆 essere usata in tutti i metodi ma risulta prolissa ed inutile ad eccezione del caso menzionato sopra
L'oggetto  this Java possiede un oggetto che permette di fare riferimento all'istanza in cui ci si trova Si usa per risolvere problemi di ambiguit sulle variabili public  Animale(String nome) { this . nome  = nome; } public   class  Fattoria { public   void  addAnimale(Animale animale) { animale.setFattoria( this ); } } Oppure per passare "se stessi"
Polimorfismo (ancora!) Abbiamo visto che il metodo  parla()  della classe Cane ha  un comportamento diverso da quello della classe base, 竪 un comportamento  pi湛 specializzato il metodo  parla()  pu嘆 utilizzare quanto fatto nella classe base richiamando il metodo  super.parla() public   class  Cane  extends  Animale { public  String parla() { return   "Ciao, io sono "  +  super .parla() +  " e faccio baubau" ; } }
Incapsulamento e Polimorfismo /1 Esempio 2 E' molto utile utilizzare l'ereditariet e l'incapsulamento insieme Supponiamo che la nostra classe Animale gestisca il livello di fame public   class  Animale { private  String  nome ; private   int   fame  = 0; public   int  getFame() { return   fame ; } protected   void  setFame( int  fame) { if  (fame < 0) {  this . fame  = 0; }  else   if  (fame > 10) {  this . fame  = 10; }  else  {  this . fame  = fame; } } } Notare che  setFame()  竪  protected E' impossibile dare un valore non corretto all'attributo fame Domanda: Perch辿 竪  protected ?
Incapsulamento e Polimorfismo /2 Quando l'animale si muove la fame aumenta public   void  muovi() { if  (possoAncoraMuovermi()) {  aumentaFame(); } } Prima si verifica se pu嘆 ancora muoversi (linea 2) Se pu嘆 muoversi la fame aumenta (linea 3) Il metodo  muovi()  竪  public  quindi tutti possono richiamarlo
Incapsulamento e Polimorfismo /3 Il metodo  possoAncoraMuovermi()  竪  public  perch竪 pu嘆 essere utile al chiamante Il metodo  aumentaFame()  pu嘆 essere richiamato solo dalle classi derivate, questo impedisce che qualcuno lo chiami falsandone il valore public   boolean  possoAncoraMuovermi() { if  ( fame  < 10) {  return   true ;  } return   false ; } protected   void  aumentaFame() { ++ fame ;  }
Incapsulamento e Polimorfismo /4 Facciamo muovere Fido public   class  TestCorsaFido { public   static   void  main(String[] args) { Cane fido =  new  Cane( &quot;Fido&quot; ); while  (fido.possoAncoraMuovermi()) { int  fameAttuale = fido.getFame(); if  (fameAttuale < 3) { System. out .println( &quot;Sono pieno &quot;  + fameAttuale); }  else   if  (fameAttuale < 6) { System. out .println( &quot;Ho un languorino &quot;  + fameAttuale); }  else  { System. out .println( &quot;Ho fame!!! &quot;  + fameAttuale); } fido.muovi(); } } }  // chiude la classe
Incapsulamento e Polimorfismo /4 Il risultato della corsa di Fido Sono pieno 0 Sono pieno 1 Sono pieno 2 Ho un languorino 3 Ho un languorino 4 Ho un languorino 5 Ho fame!!! 6 Ho fame!!! 7 Ho fame!!! 8 Ho fame!!! 9
Incapsulamento e Polimorfismo /5 Esempio 3 La classe Cane riutilizza l'algoritmo della classe Animale per aumentare la fame ma ogni animale brucia energie a velocit diverse dobbiamo fare in modo che sia facile aggiungere nuovi animali alla nostra fattoria con  comportamenti specializzati l'algoritmo dell'aumento fame sta nel metodo protected   void  aumentaFame() { ++ fame ; }
Incapsulamento e Polimorfismo /6 Fido diventa affamato pi湛 velocemente basta ridefinire cosa fa il metodo  aumentaFame()  nella classe Cane public   class  Cane  extends  Animale { public  Cane(String nome) { super (nome); } protected   void  aumentaFame() { int  fameAttuale = getFame(); setFame(fameAttuale + 3); } }
Incapsulamento e Polimorfismo /7 Senza modificare altro codice e rieseguendo il programma di test si ottiene Sono pieno 0 Ho un languorino 3 Ho fame!!! 6 Ho fame!!! 9
Incapsulamento e Polimorfismo /8 Il polimorfismo permette di trattare le classi derivate come se fossero tutte del tipo della classe base Cane braccobaldo =  new  Cane( &quot;Braccobaldo&quot; ); Animale fido =  new  Cane( &quot;Fido&quot; ); System. out .println(fido.getNome() + braccobaldo.getNome()); Alla linea 2 viene creato un oggetto Cane ma viene assegnato ad un oggetto di tipo Animale L'assegnazione 竪 lecita perch辿 Cane deriva da Animale Il contrario darebbe errore
Incapsulamento e Polimorfismo /9 Cosa succede se si vuole &quot;convertire&quot; un oggetto Animale generico in una classe derivata? Se l'assegnazione 竪 lecita, ovvero l'oggetto generico 竪 di tipo compatibile basta fare un cast (downcast) Se l'assegnazione non 竪 lecita viene generato un errore a runtime (non a compile time)
Incapsulamento e Polimorfismo /10 Cast - da classe base a derivata Il cast si ottiene mettendo tra parentesi il tipo desiderato davanti alla variabile da  &quot;convertire&quot; Animale fido =  new  Cane( &quot;Fido&quot; ); Animale silvestro =  new  Gatto( &quot;Silvestro&quot; ); // e' corretto perche' silvestro e' di tipo gatto Gatto g = (Gatto)silvestro; // genera errore perche' fido e' un cane non un gatto Gatto g1 = (Gatto)fido;
Incapsulamento e Polimorfismo /11 operatore instanceof E' possibile testare un oggetto per scoprire il suo tipo utilizzando l'operatore instanceof Animale fido =  new  Cane( &quot;Fido&quot; ); if  (fido  instanceof  Gatto) { System. out .println( &quot;Fido e' un gatto&quot; ); }  else   if  (fido  instanceof  Cane) { System. out .println( &quot;Fido e' un cane&quot; ); } L'utilizzo di instanceof non 竪 una buona pratica OOP Il metodo 竪 particolarmente pesante da un punto di vita prestazionale
Override dei metodi Quando si  ridefinisce  un metodo in una classe derivata si dice che si fa  override Il metodo  aumentaFame()  nella classe Cane 竪 quindi un override del corrispondente metodo della classe Animale &quot;Fare override&quot;, &quot;derivare&quot;, &quot;specializzare&quot; sono tutti sinomini Non si faccia confusione con overload dei metodi
Overload e override Overload  due o pi湛 metodi  della stessa classe  hanno lo stesso nome ma prendono argomenti diversi Override  un metodo presente nella  classe base  viene  ridefinito  in una o pi湛  classi derivate
Classi e metodi astratte /1 Esempio 4 All'inizio abbiamo definito la classe Animale con il metodo  parla() Questo metodo non aveva nessuna utilit nella classe base Esiste un modo per dichiarare questo metodo senza implementazione Si forzano le classi derivate ad implementarlo (altrimenti non compilano) in modo da dargli la  corretta  implementazione Una classe astratta non pu嘆 essere istanziata
Classi e metodi astratti /2 Si crea una classe con il metodo parla  astratto public   class  Animale { public  String parla() { return   &quot;Errore: Animale generico&quot; ; } } La classe diventa public   abstract class  Animale { public   abstract  String parla(); }
In Java tutto 竪 un oggetto Classe Object /1 In Java tutte le classi hanno una classe base  implicita Questa classe di chiama Object e contiene dei metodi utili alla Java Virtual Machine Scrivere public   class  Animale  extends  Object { } public   class  Animale { } Equivale a scrivere
In Java tutto e' un oggetto Classe Object /2 La classe Object e' detta la radice della gerarchia delle classi Java Tra i metodi contenuti troviamo equals e toString public   class  Object { // Verifica se due oggetti sono uguali public   boolean  equals(Object obj) { } // Converte un oggetto in stringa public  String toString() { } }
Polimorfismo per interfacce /1 Si 竪 visto che in Java si pu嘆 derivare da una sola classe Pu嘆 essere necessario definire un nuovo oggetto con caratteristiche provenienti da due oggetti diversi Un pappagallo vola, un cane nuota Si potrebbe creare una classe PuoVolare ed una PuoNuotare che estendono Animale ma perdono di genericit Anche un aereo &quot;pu嘆 volare&quot; e una barca &quot;pu嘆 nuotare&quot;
Polimorfismo per interfacce /2 Un pappagallo pu嘆 volare ma un'anatra pu嘆 sia volare che nuotare Utilizzando l'ereditariet abbiamo
Polimorfismo per interfacce /3 La classe PuoVolareENuotare 竪 necessaria ma appesantisce inutilmente la gerarchia delle classi Meglio sarebbe avere...
Polimorfismo per interfacce /4
Polimorfismo per interfacce /4 Questo si realizza in Java utilizzando le interfacce (parola riservata  interface ) Le  interface  sono simili alle classi astratte Esse hanno la dichiarazione dei metodi senza implementazione Possono avere  solo  metodi pubblic Non  possono avere attributi Le classi derivate  implementano  le interfacce
Polimorfismo per interfacce /5 Le nostre classi diventano public   interface  PuoNuotare { public   boolean  nuota(); } public   interface  PuoVolare { public   boolean  vola(); }
Polimorfismo per interfacce /6 public   class  Cane  extends  Animale  implements  PuoNuotare { ... ... public   boolean  nuota() { return   true ; } } public   class  Pappagallo  extends  Animale  implements  PuoVolare { ... ... public   boolean  vola() { return   true ; } }
Polimorfismo per interfacce /7 public   class  Anatra  extends  Animale  implements  PuoNuotare, PuoVolare { ... ... public   boolean  nuota() { return   true ; } public   boolean  vola() { return   true ; } }
Quando si  devono usare le interfacce Sempre!!! Le interfacce permettono di disaccoppiare l'implementazione dalla propria definizione Questo significa che e' facile sostituire il  comportamento  di una classe intervenendo solo sulla particolare implementazione Tutte le tecnologie Java (Servlet, EJB, JMS) sono basate sul concetto di interfaccia
I package /1 L'edizione Standard Edition di Java (SE) contiene circa 4000 tra classi ed interfacce L'edizione Enterprise Edition di Java (EE) contiene circa 300 tra classi ed interfacce Una tale mole di oggetti richiede una organizzazione razionale Le classi vengono organizzate in package Ogni package contiene le classi logicamente correlate
I package /2 I principali package in java sono java.lang String, Integer, Long java.lang.math Sin, Cos, min, max java.io File java.util Date, List java.sql Connection, Timestamp
I package /3 Se si vuole usare un metodo o una classe di un package bisogna importarlo nel proprio programma Le classi presenti in java.lang vengono importate implicitamente E' possibile, anzi  caldamente consigliato , mettere le proprie classi in package Si possono importare tutti i package che si vuole, non esistono limiti
I package /4 package  corso.java; import  java.io.File; import  java.util.Date; public   class  EsempioPackage { public   static   void  main(String[] args) { System. out .println( &quot;Radice quadrata &quot;  + Math. sqrt (144)); File f =  new  File( &quot;a.txt&quot; ); System. out .println( &quot;Dimensione file &quot;  + f.length()); Date oggi =  new  Date(); System. out .println( &quot;Oggi e' &quot;  + oggi); } }
I package /5 Un proprio package si definire con la parola riservata  package Un package puo' avere livelli come una directory Ogni livello viene separato dal carattere punto java.lang
I package /6 Per utilizzare le classi di un package si deve fare l'import tramite la parola riservata import Non e' necessario fare import per le classi presenti in java.lang le classi presenti nello stesso package import  java.io.File; File f =  new  File( &quot;a.txt&quot; );
Import singola classe Import intero package E' possibile effettuare l'import di una sola classe import  java.io.File; import  java.util.Date; import  java.io.*; import  java.util.Date; Oppure di un intero package (utilizzando la sintassi con  asterisco ) L'import di un intero package 竪 una  bad practice  e andrebbe utilizzato sono in quei rarissimi casi in cui si rivela indispensabile
Package e classi con nomi uguali /1 Java ha due classi Date una usata per un uso generale (java.util.Date) una usata per l'accesso tramite SQL (java.sql.Date) Come faccio ad utilizzare entrambe nello stesso programma? import  java.util.Date; import  java.sql.Date;  ** ERRORE DI COMPILAZIONE ** // oggetto di tipo java.util.Date Date oggi =  new  Date(); // Questa e' una SQL DATE ma come faccio a dirlo al compilatore? // oggetto di tipo java.sql.Date Date sqlOggi =  new  Date(oggi.getTime());
Package e classi con nomi uguali /2 Bisogna risolvere l'ambiguit in fase di dichiarazione della variabile import  java.util.Date; Date oggi =  new  Date(); java.sql.Date sqlOggi =  new  java.sql.Date(oggi.getTime()); Si effettua l'import  solo  di una delle due (non importa quale) Si dichiara la seconda con il FQN (Full Qualified Name) ovvero tutto il nome package e della classe (come alla linea 3)

More Related Content

Java 02

  • 1. Java Ereditariet e Polimorfismo applicate in Java Davide Ficano [email_address]
  • 2. Ereditariet Polimorfismo Abbiamo detto che Ereditariet significa avere un oggetto base con un insieme di stati e comportamenti presenti anche in oggetti derivati Polimorfismo significa assumere significati specifici in diversi contesti
  • 4. Classe Base Animale public class Animale { private String nome ; public Animale(String nuovoNome) { nome = nuovoNome; } public String getNome() { return nome ; } public String parla() { return &quot;Errore: Animale generico&quot; ; } } Non stiamo descrivendo nessuna specie animale particolare quindi non sappiamo qual'竪 il verso * Notare che non esiste il metodo setNome(...) per fare in modo che una volta dato il nome (nel costruttore) all'animale non lo si possa pi湛 cambiare
  • 5. Classe specializzata Cane &quot;extends&quot; Animale public class Cane extends Animale { public Cane(String nome) { super (nome); } public String parla() { return &quot;Ciao, io sono &quot; + getNome() + &quot; e faccio baubau&quot; ; } } Viene usata la parola extends per derivare dalla classe Animale Il costruttore richiama quello della classe base tramite la parola riservata super Il metodo parla() viene ridefinito. Abbiamo applicato il Polimorfismo Viene richiamato il metodo getNome della classe base
  • 6. Note su &quot;extends&quot; La parola riservata extends serve a derivare da una classe base Si pu嘆 derivare solo da una classe Avere l'ereditariet singola evita le ambiguit dovute alla presenta dello stesso metodo in due classi base: quale chiamo? public class Cane extends Animale, Lassie { } La Sintassi 竪 sbagliata perch辿 extends accetta solo una classe
  • 7. Costruttori ed ereditariet Esempio 1 I costruttori non vengono ereditati sono comunque accessibili tramite la sintassi super (...) public class Cane extends Animale { ... ... } Non compila public class Cane extends Animale { public Cane(String nome) { super (nome); } } La classe a sinistra non compila perch竪 non &quot;vede&quot; il costruttore della classe base La classe a destra dichiara un costruttore uguale a quello della classe base e poi lo richiama con la sintassi super (...)
  • 8. Utilizzo di super nei metodi /1 Anche i metodi possono richiamare super ma solo per riferirsi ad un metodo della classe base Significa che un metodo non pu嘆 richiamare un costruttore tramite super public class Cane extends Animale { public String parla() { super ( &quot;fido&quot; ); return ...; } } Non compila, c'e' errore alla linea nr 3. un costruttore non puo' essere richiamato in un metodo Domanda: Perch辿 un costruttore non pu嘆 essere richiamato in un metodo?
  • 9. Utilizzo di super nei metodi /2 E' utile usare super nei metodi quando si vuole richiamare il metodo con lo stesso nome presente nella classe base public class Cane extends Animale { public String parla() { return &quot;Ciao, io sono &quot; + super .parla() + &quot; e faccio baubau&quot; ; } } Il metodo Cane.parla richiama il metodo Animale.parla la sintassi super.nomeMetodo pu嘆 essere usata in tutti i metodi ma risulta prolissa ed inutile ad eccezione del caso menzionato sopra
  • 10. L'oggetto this Java possiede un oggetto che permette di fare riferimento all'istanza in cui ci si trova Si usa per risolvere problemi di ambiguit sulle variabili public Animale(String nome) { this . nome = nome; } public class Fattoria { public void addAnimale(Animale animale) { animale.setFattoria( this ); } } Oppure per passare &quot;se stessi&quot;
  • 11. Polimorfismo (ancora!) Abbiamo visto che il metodo parla() della classe Cane ha un comportamento diverso da quello della classe base, 竪 un comportamento pi湛 specializzato il metodo parla() pu嘆 utilizzare quanto fatto nella classe base richiamando il metodo super.parla() public class Cane extends Animale { public String parla() { return &quot;Ciao, io sono &quot; + super .parla() + &quot; e faccio baubau&quot; ; } }
  • 12. Incapsulamento e Polimorfismo /1 Esempio 2 E' molto utile utilizzare l'ereditariet e l'incapsulamento insieme Supponiamo che la nostra classe Animale gestisca il livello di fame public class Animale { private String nome ; private int fame = 0; public int getFame() { return fame ; } protected void setFame( int fame) { if (fame < 0) { this . fame = 0; } else if (fame > 10) { this . fame = 10; } else { this . fame = fame; } } } Notare che setFame() 竪 protected E' impossibile dare un valore non corretto all'attributo fame Domanda: Perch辿 竪 protected ?
  • 13. Incapsulamento e Polimorfismo /2 Quando l'animale si muove la fame aumenta public void muovi() { if (possoAncoraMuovermi()) { aumentaFame(); } } Prima si verifica se pu嘆 ancora muoversi (linea 2) Se pu嘆 muoversi la fame aumenta (linea 3) Il metodo muovi() 竪 public quindi tutti possono richiamarlo
  • 14. Incapsulamento e Polimorfismo /3 Il metodo possoAncoraMuovermi() 竪 public perch竪 pu嘆 essere utile al chiamante Il metodo aumentaFame() pu嘆 essere richiamato solo dalle classi derivate, questo impedisce che qualcuno lo chiami falsandone il valore public boolean possoAncoraMuovermi() { if ( fame < 10) { return true ; } return false ; } protected void aumentaFame() { ++ fame ; }
  • 15. Incapsulamento e Polimorfismo /4 Facciamo muovere Fido public class TestCorsaFido { public static void main(String[] args) { Cane fido = new Cane( &quot;Fido&quot; ); while (fido.possoAncoraMuovermi()) { int fameAttuale = fido.getFame(); if (fameAttuale < 3) { System. out .println( &quot;Sono pieno &quot; + fameAttuale); } else if (fameAttuale < 6) { System. out .println( &quot;Ho un languorino &quot; + fameAttuale); } else { System. out .println( &quot;Ho fame!!! &quot; + fameAttuale); } fido.muovi(); } } } // chiude la classe
  • 16. Incapsulamento e Polimorfismo /4 Il risultato della corsa di Fido Sono pieno 0 Sono pieno 1 Sono pieno 2 Ho un languorino 3 Ho un languorino 4 Ho un languorino 5 Ho fame!!! 6 Ho fame!!! 7 Ho fame!!! 8 Ho fame!!! 9
  • 17. Incapsulamento e Polimorfismo /5 Esempio 3 La classe Cane riutilizza l'algoritmo della classe Animale per aumentare la fame ma ogni animale brucia energie a velocit diverse dobbiamo fare in modo che sia facile aggiungere nuovi animali alla nostra fattoria con comportamenti specializzati l'algoritmo dell'aumento fame sta nel metodo protected void aumentaFame() { ++ fame ; }
  • 18. Incapsulamento e Polimorfismo /6 Fido diventa affamato pi湛 velocemente basta ridefinire cosa fa il metodo aumentaFame() nella classe Cane public class Cane extends Animale { public Cane(String nome) { super (nome); } protected void aumentaFame() { int fameAttuale = getFame(); setFame(fameAttuale + 3); } }
  • 19. Incapsulamento e Polimorfismo /7 Senza modificare altro codice e rieseguendo il programma di test si ottiene Sono pieno 0 Ho un languorino 3 Ho fame!!! 6 Ho fame!!! 9
  • 20. Incapsulamento e Polimorfismo /8 Il polimorfismo permette di trattare le classi derivate come se fossero tutte del tipo della classe base Cane braccobaldo = new Cane( &quot;Braccobaldo&quot; ); Animale fido = new Cane( &quot;Fido&quot; ); System. out .println(fido.getNome() + braccobaldo.getNome()); Alla linea 2 viene creato un oggetto Cane ma viene assegnato ad un oggetto di tipo Animale L'assegnazione 竪 lecita perch辿 Cane deriva da Animale Il contrario darebbe errore
  • 21. Incapsulamento e Polimorfismo /9 Cosa succede se si vuole &quot;convertire&quot; un oggetto Animale generico in una classe derivata? Se l'assegnazione 竪 lecita, ovvero l'oggetto generico 竪 di tipo compatibile basta fare un cast (downcast) Se l'assegnazione non 竪 lecita viene generato un errore a runtime (non a compile time)
  • 22. Incapsulamento e Polimorfismo /10 Cast - da classe base a derivata Il cast si ottiene mettendo tra parentesi il tipo desiderato davanti alla variabile da &quot;convertire&quot; Animale fido = new Cane( &quot;Fido&quot; ); Animale silvestro = new Gatto( &quot;Silvestro&quot; ); // e' corretto perche' silvestro e' di tipo gatto Gatto g = (Gatto)silvestro; // genera errore perche' fido e' un cane non un gatto Gatto g1 = (Gatto)fido;
  • 23. Incapsulamento e Polimorfismo /11 operatore instanceof E' possibile testare un oggetto per scoprire il suo tipo utilizzando l'operatore instanceof Animale fido = new Cane( &quot;Fido&quot; ); if (fido instanceof Gatto) { System. out .println( &quot;Fido e' un gatto&quot; ); } else if (fido instanceof Cane) { System. out .println( &quot;Fido e' un cane&quot; ); } L'utilizzo di instanceof non 竪 una buona pratica OOP Il metodo 竪 particolarmente pesante da un punto di vita prestazionale
  • 24. Override dei metodi Quando si ridefinisce un metodo in una classe derivata si dice che si fa override Il metodo aumentaFame() nella classe Cane 竪 quindi un override del corrispondente metodo della classe Animale &quot;Fare override&quot;, &quot;derivare&quot;, &quot;specializzare&quot; sono tutti sinomini Non si faccia confusione con overload dei metodi
  • 25. Overload e override Overload due o pi湛 metodi della stessa classe hanno lo stesso nome ma prendono argomenti diversi Override un metodo presente nella classe base viene ridefinito in una o pi湛 classi derivate
  • 26. Classi e metodi astratte /1 Esempio 4 All'inizio abbiamo definito la classe Animale con il metodo parla() Questo metodo non aveva nessuna utilit nella classe base Esiste un modo per dichiarare questo metodo senza implementazione Si forzano le classi derivate ad implementarlo (altrimenti non compilano) in modo da dargli la corretta implementazione Una classe astratta non pu嘆 essere istanziata
  • 27. Classi e metodi astratti /2 Si crea una classe con il metodo parla astratto public class Animale { public String parla() { return &quot;Errore: Animale generico&quot; ; } } La classe diventa public abstract class Animale { public abstract String parla(); }
  • 28. In Java tutto 竪 un oggetto Classe Object /1 In Java tutte le classi hanno una classe base implicita Questa classe di chiama Object e contiene dei metodi utili alla Java Virtual Machine Scrivere public class Animale extends Object { } public class Animale { } Equivale a scrivere
  • 29. In Java tutto e' un oggetto Classe Object /2 La classe Object e' detta la radice della gerarchia delle classi Java Tra i metodi contenuti troviamo equals e toString public class Object { // Verifica se due oggetti sono uguali public boolean equals(Object obj) { } // Converte un oggetto in stringa public String toString() { } }
  • 30. Polimorfismo per interfacce /1 Si 竪 visto che in Java si pu嘆 derivare da una sola classe Pu嘆 essere necessario definire un nuovo oggetto con caratteristiche provenienti da due oggetti diversi Un pappagallo vola, un cane nuota Si potrebbe creare una classe PuoVolare ed una PuoNuotare che estendono Animale ma perdono di genericit Anche un aereo &quot;pu嘆 volare&quot; e una barca &quot;pu嘆 nuotare&quot;
  • 31. Polimorfismo per interfacce /2 Un pappagallo pu嘆 volare ma un'anatra pu嘆 sia volare che nuotare Utilizzando l'ereditariet abbiamo
  • 32. Polimorfismo per interfacce /3 La classe PuoVolareENuotare 竪 necessaria ma appesantisce inutilmente la gerarchia delle classi Meglio sarebbe avere...
  • 34. Polimorfismo per interfacce /4 Questo si realizza in Java utilizzando le interfacce (parola riservata interface ) Le interface sono simili alle classi astratte Esse hanno la dichiarazione dei metodi senza implementazione Possono avere solo metodi pubblic Non possono avere attributi Le classi derivate implementano le interfacce
  • 35. Polimorfismo per interfacce /5 Le nostre classi diventano public interface PuoNuotare { public boolean nuota(); } public interface PuoVolare { public boolean vola(); }
  • 36. Polimorfismo per interfacce /6 public class Cane extends Animale implements PuoNuotare { ... ... public boolean nuota() { return true ; } } public class Pappagallo extends Animale implements PuoVolare { ... ... public boolean vola() { return true ; } }
  • 37. Polimorfismo per interfacce /7 public class Anatra extends Animale implements PuoNuotare, PuoVolare { ... ... public boolean nuota() { return true ; } public boolean vola() { return true ; } }
  • 38. Quando si devono usare le interfacce Sempre!!! Le interfacce permettono di disaccoppiare l'implementazione dalla propria definizione Questo significa che e' facile sostituire il comportamento di una classe intervenendo solo sulla particolare implementazione Tutte le tecnologie Java (Servlet, EJB, JMS) sono basate sul concetto di interfaccia
  • 39. I package /1 L'edizione Standard Edition di Java (SE) contiene circa 4000 tra classi ed interfacce L'edizione Enterprise Edition di Java (EE) contiene circa 300 tra classi ed interfacce Una tale mole di oggetti richiede una organizzazione razionale Le classi vengono organizzate in package Ogni package contiene le classi logicamente correlate
  • 40. I package /2 I principali package in java sono java.lang String, Integer, Long java.lang.math Sin, Cos, min, max java.io File java.util Date, List java.sql Connection, Timestamp
  • 41. I package /3 Se si vuole usare un metodo o una classe di un package bisogna importarlo nel proprio programma Le classi presenti in java.lang vengono importate implicitamente E' possibile, anzi caldamente consigliato , mettere le proprie classi in package Si possono importare tutti i package che si vuole, non esistono limiti
  • 42. I package /4 package corso.java; import java.io.File; import java.util.Date; public class EsempioPackage { public static void main(String[] args) { System. out .println( &quot;Radice quadrata &quot; + Math. sqrt (144)); File f = new File( &quot;a.txt&quot; ); System. out .println( &quot;Dimensione file &quot; + f.length()); Date oggi = new Date(); System. out .println( &quot;Oggi e' &quot; + oggi); } }
  • 43. I package /5 Un proprio package si definire con la parola riservata package Un package puo' avere livelli come una directory Ogni livello viene separato dal carattere punto java.lang
  • 44. I package /6 Per utilizzare le classi di un package si deve fare l'import tramite la parola riservata import Non e' necessario fare import per le classi presenti in java.lang le classi presenti nello stesso package import java.io.File; File f = new File( &quot;a.txt&quot; );
  • 45. Import singola classe Import intero package E' possibile effettuare l'import di una sola classe import java.io.File; import java.util.Date; import java.io.*; import java.util.Date; Oppure di un intero package (utilizzando la sintassi con asterisco ) L'import di un intero package 竪 una bad practice e andrebbe utilizzato sono in quei rarissimi casi in cui si rivela indispensabile
  • 46. Package e classi con nomi uguali /1 Java ha due classi Date una usata per un uso generale (java.util.Date) una usata per l'accesso tramite SQL (java.sql.Date) Come faccio ad utilizzare entrambe nello stesso programma? import java.util.Date; import java.sql.Date; ** ERRORE DI COMPILAZIONE ** // oggetto di tipo java.util.Date Date oggi = new Date(); // Questa e' una SQL DATE ma come faccio a dirlo al compilatore? // oggetto di tipo java.sql.Date Date sqlOggi = new Date(oggi.getTime());
  • 47. Package e classi con nomi uguali /2 Bisogna risolvere l'ambiguit in fase di dichiarazione della variabile import java.util.Date; Date oggi = new Date(); java.sql.Date sqlOggi = new java.sql.Date(oggi.getTime()); Si effettua l'import solo di una delle due (non importa quale) Si dichiara la seconda con il FQN (Full Qualified Name) ovvero tutto il nome package e della classe (come alla linea 3)