====== Evoluzione, non rivoluzione ====== PREV [[dichiarazioni_di_classi_generiche]] NEXT [[reificazione]] ''Migrare gradualmente il codice all'utilizzo dei generics (//evoluzione//) senza modifche radicali (//rivoluzione//)'' ===== Evoluzione ===== L'implementazione dei generics permette che il vecchio codice venga compilato ed eseguito anche con l'utilizzo delle nuove librerie L'evoluzione è più forte della retro compatibilità: non esistono più versioni delle classi e delle librerie ma una sola versione (grazie alla type //erasure//) compatibile Non sempre è possibile mettere mano a tutto il codice * È costoso * Non abbiamo accesso ai sorgenti * Possiamo mettere le mani solo sul client o sulla libreria * ... E' quindi necessario procedere per passi ===== Raw type e generic type ===== I raw types sono la controparte legacy dei generic types ^Generic^Raw^ |Stack| Stack| |List |List| |ArrayStack| ArrayStack| ===== Casi di evoluzione ===== Dovendo utilizzare client con librerie abbiamo 4 casi ^Client / Libreria^Libreria Generic^Libreria Legacy^ ^Client Generic |CG,LG |CG,LL| ^Client Legacy |CL,LG |CL,LL| ==== Client Generic, Libreria Generic ==== Non pone grossi problemi (è il punto di arrivo). Per arrivare a questo punto di norma tutte le occorrenze di Object vengono sostituite con opportuni parametri di tipo (solo dove ha senso) ==== Client Legacy, Libreria Legacy ==== Di norma è il punto di partenza dell'evoluzione in cui sono presenti solo raw type public static void fai(List l) { ...} questo codice genera un //warning//: List is a raw type. References to generic type List should be parametrized ==== Client Legacy, Libreria generica ==== E' il caso più importante di retro compatibilità: il Collection framework di java 5 deve funzionare con i client di java 1.4. Per supportare l'evoluzione, per ogni parametro generico java riconosce anche il suo raw type ''Ogni tipo parametrico è sottotipo del corrispondente raw type'' Un oggetto “parametrico” può quindi essere utilizzato quando ci si aspetta un raw type ==== Unchecked conversion warning ==== Di norma è un errore utilizzare un supertipo di T quando ci si aspetta un oggetto di tipo T. Eccezione alla regola: è possibile utilizzare un //raw type// al posto di uno dei corrispondenti tipi parametrici Viene tuttavia generato un //__unchecked__ conversion warning// List a = new ArrayList(); // OK, normale sottotipizzazione List x = new ArrayList(); // OK ... ma genera un Unchecked Conversion Warning Type safety: the expression of type ArrayList needs unchecked conversion to conform to List //__Unchecked__ conversion warning// indica che il compilatore non è in grado di ofrire le stesse garanzie che sono possibili quando i generics vengono utilizzati in maniera uniforme. Vengono comunque assicurate le stesse (???) garanzie di quando non si utilizzano per niente i generics (!!!) ''Non vale la cast iron guarantee'' ==== Client generico, Libreria Legacy ==== List l = new ArrayList(); l.add(elem); Il codice compila ma viene generato un ''__Unchecked__ Call Warning'' Pippo.java:7: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.List l.add(elem); :!: Se i warning vi danno doia ... @SuppressWarnings("unchecked") (a vostro rischio e pericolo)