martedì 26 marzo 2013

Conversioni di tipo tra superclasse e sottoclasse


Conversioni di tipo fra sottoclasse e superclasse


Può esserci la necessità di memorizzare un riferimento di una sottoclasse in un riferimento a superclasse. Questo è possibile e avviene in modo automatico. Consideriamo :
  • Sottoclasse extendes Superclasse
  • Superclasse extendes Object (tutte le classi lo fanno)

             SottoClasse ssc = new SottoClasse();
             SuperClasse ss = new SuperClasse();
             Object ogg = new Object();      
             ss = ssc;
             ogg=ssc;
Abbiamo tre riferimenti diversi che vedono la stessa area di memoria :
 
L' esigenza nasce se si devono trattare in modo simile tutte le sottoclassi di una certa superclasse. consideriamo :
  • Una superclasse
  • Un insieme di sottoclassi
  • Una classe "trattante" che riceve in ingresso una qualunque sottoclasse e esegue una certa operazione, compatibile con tutte le sottoclassi.
Si può pensare di aggiungere metodi con firma diversa per ogni classe oppure implementare il meccanismo descritto sopra :
  • La classe trattante riceve sempre la superclasse e quindi non cambia mai
  • Ogni sottoclasse ha un suo metodo particolare che implementa il suo comportamento
Un esempio semplice è:

public class SuperClasse {
       public static void main(String[] args) {
             SuperClasse sc = new SuperClasse();
             SottoClasseA A = new SottoClasseA();
             SottoClasseB B = new SottoClasseB();
             SottoClasseC C = new SottoClasseC();
             SottoClasseD D = new SottoClasseD();

             metodozzo(sc);
             sc = A;
             metodozzo(sc);
             sc = B;
             metodozzo(sc);
             sc = C;
             metodozzo(sc);
             sc = D;
             metodozzo(sc);
       }

       public static void metodozzo(SuperClasse sc) {
             sc.stampaLettera();
       }
       public String stampaLettera() {
             System.out.println("0");
             return "0";
       }

}

class SottoClasseA extends SuperClasse {
       public String stampaLettera() {
             System.out.println("A");
             return "A";
       }
}
class SottoClasseB extends SuperClasse {
       public String stampaLettera() {
             System.out.println("B");
             return "B";
       }
}

class SottoClasseC extends SuperClasse {
       public String stampaLettera() {
             System.out.println("C");
             return "C";
       }
}
class SottoClasseD extends SuperClasse {
       public String stampaLettera() {
             System.out.println("D");
             return "D";
       }
}
 
Il flusso dal metodozzo rimane invariato. Ogni volta si passa una SuperClasse e poi a seconda dell'oggetto viene invocato il giusto metodo. In questo modo se domani qualcuno vuole aggiungere una sottoclasse nuova, basta che scriva un metodo stampaLettera e questa sottoclasse verrà trattata come le altre senza aggiungere codice.
Se invece si decide per la riscrittura dei metodi si avrebbe una cosa così:
public class SuperClasse {
       public static void main(String[] args) {
             SuperClasse sc = new SuperClasse();
             SottoClasseA A = new SottoClasseA();
             SottoClasseB B = new SottoClasseB();
             SottoClasseC C = new SottoClasseC();
             SottoClasseD D = new SottoClasseD();
             metodozzo(sc);
             sc = A;
             metodozzo(sc);
             sc = B;
             metodozzo(sc);
             sc = C;
             metodozzo(sc);
             sc = D;
             metodozzo(sc);
       }
       public static void metodozzo(SuperClasse sc) {
             sc.stampaLettera();
       }
       public static void metodozzo(SottoClasseA sc) {
             sc.stampaLettera();
       }
       public static void metodozzo(SottoClasseB sc) {
             sc.stampaLettera();
       }
       public static void metodozzo(SottoClasseC sc) {
             sc.stampaLettera();
       }
       public static void metodozzo(SottoClasseD sc) {
             sc.stampaLettera();
       }
       public String stampaLettera() {
             System.out.println("0");
             return "0";
       }
}
class SottoClasseA extends SuperClasse {
       public String stampaLettera() {
             System.out.println("A");
             return "A";
       }
}
class SottoClasseB extends SuperClasse {
       public String stampaLettera() {
             System.out.println("B");
             return "B";
       }
}
class SottoClasseC extends SuperClasse {
       public String stampaLettera() {
             System.out.println("C");
             return "C";
       }
}
class SottoClasseD extends SuperClasse {
       public String stampaLettera() {
             System.out.println("D");
             return "D";
       }
}
Cioè per ogni sottoclasse il metodo metodozzo va riscritto! Oltre ad essere faticoso ricordarsi tutti i punti dove intervenire in caso di sottoclasse nuova si peggiora la manutenzione dello stesso metodo, perchè una eventuale modifica a metodozzo va riscritta per tutti i metodi!

Nessun commento:

Posta un commento