import java.util.*; //////////////////////////////////////////////////////////// //Déclarations préliminaires pour les exs d'après //////////////////////////////////////////////////////////// class Truc{ T x; void set(T xx){ x=xx; } } class Mere { void show() { System.out.println("Je suis une Mere"); } } class FilleUn extends Mere { void show() { System.out.println("Je suis une FilleUn"); } } class FilleDeux extends Mere { void show() { System.out.println("Je suis une FilleDeux"); } } //////////////////////////////////////////////////////////// // vs : les propriétés des sous type en generique classique vs wildcard //////////////////////////////////////////////////////////// class TestUn{ public static void main(String[] args){ /////////////////////////////////////////////////////////////////////////////////////////////////// ////// Propriété "non héritage avec généricité" : Truc PAS sous type de Truc /////// /////////////////////////////////////////////////////////////////////////////////////////////////// Truc tMere = new Truc<>(); Truc tFille = new Truc<>(); //si Truc sous type de Truc alors on pourrait faire //tMere = tFille; //tMere.set(new Mere()); //et là on aurait tFille donc le x est Mere! /////////////////////////////////////////////////////////////////////////////////////////////////////// //////Propriété "héritage avec les wildcard" : Truc EST sous type de Truc //// //////////////////////////////////////////////////////////////////////////////////////////////////////// Truc trucFilleUn = new Truc<>(); Truc trucWild = new Truc<>(); trucWild = trucFilleUn; //attention Truc n'EST PAS sous type de Truc, sinon par transitivité on aurait Truc sous type Truc //// //et on pourrait alors faire tMere = trucWild; et comme avant on aurait un tMere qui point vers un tFille //trucWild.set(new Mere()); //comme Truc sous type de Truc, penser quand on a un objet Truc que c'est peut etre un Truc qui pointe dessus, //et donc aucune opération permettant de changer un FilleUn en Mere sera autorisée (après à voir comment le compilo track ça, ici avec juste l'affectation) } } //////////////////////////////////////////////////////////////// ////// avantage de la propriété d'héritage des wildcard /////// //////////////////////////////////////////////////////////////// //ex0: TP6, // interface IJeu{ // .. // ArrayList genererFils(); // // } // avec cette interface, alors on ajoute juste "class Taquin IMPLEMENTS IJeu", et tout est ok // (en particulier ArrayList genererFils(); est ok) // alors que avec // interface IJeu{ // .. // ArrayList genererFils(); // // } // si on ajoute juste "class Taquin IMPLEMENTS IJeu", ne compile pas //ex1: cours Mr Valicov : // calculerSalaires(AL l) // fait somme l.get(i).getSalaire() // bof écrit comme cela car pas utilisable sur AL //V2:calculerSalaires(AL l) // là utilisable avec AL car sous type de AL //ex1 bis: class Test{ public static double sumOfList(List list) { double s = 0.0; for (Number n : list) s += n.doubleValue(); return s; } public static void main(String[] args){ ArrayList l = new ArrayList<>(); l.add(3.5); sumOfList(l); } } ///////////////////////////////////////////////////////////////////////////////////////// ////// Conséquence de la propriété des wildcard: le "read only" /// ///////////////////////////////////////////////////////////////////////////////////////// class TestDeux{ public static void main(String[] args){ Truc trucFilleUn = new Truc<>(); Truc trucWild = new Truc<>(); trucWild = trucFilleUn; //trucWild.set(new Mere()); //on ne peut pas faire cela, et heureusement sinon le trucFilleUn aurait un x de type Mere //autrement dit, quand on a un objet Truc, penser que c'est peut etre un Truc qui pointe dessus, //et donc aucune opération permettant de changer "dans cet objet" un FilleUn en Mere ne sera autorisée } //et donc quand manipule du Truc, on est en read only: //ne compile pas (et heureusement, sinon imaginez avec en paramètre une List //public static void sumOfListEssaiWrite(List list) { // list.add(new Mere()); // } } ///////////////////////////////////////////////////////////////////////////////////////// ////// vs : round 2 ///////////////////////////////////////////////////////////////////////////////////////// //on peut parfois transformer l'utiilisation d'une wild card en version générique: //reprenons l'ex précédent //Ex1 class TestTrois{ public static double sumOfListV2(List list) { double s = 0.0; for (Number n : list) s += n.doubleValue(); return s; } } //point positif : ici, même si c'est inutile, nous ne sommes plus "read onlye" (on pourrait faire quelque chose comme list.add(list.get(0))) //Ex2 : TP6 interface Ijeu>{ ArrayList genererFils(); } class Taquin implements Ijeu{ public ArrayList genererFils(){return null;}//return null juste pour que cela compile } //point positif : ici le genereFils de Taquin doit retourner une AL ne contenant que des taquins, //alors que avec ArrayList dans l'interface Ijeu, il aurait pu retourner une AL avec des taquins et des hanoi //point négatif : si on avait Taquin et Ijeu qui pré-existaient (sans généricité) et qu'on passe Ijeu en générique, force à génériciser Taquin //EX3 inspiré de "effective java" class Stack { E x; //pour simplifier je code un stack ne pouvant stocker qu'un seul élément public void push(E e){ x=e; } public E pop(){ E res = x; x = null; return res; } public boolean isEmpty(){ return x==null; } public void pushAll(Iterable src) { for (E e : src) push(e); } //ici on peut réécrire public void pushAllV2(Iterable src) { for (T e : src) push(e); } public void popAll(Collection dst) { while (!isEmpty()) dst.add(pop()); } //par contre pour popALl on est coincé, on ne peut pas écrire //(je ne sais pas pourquoi est interdit d'ailleurs // public void popAllV2(Collection dst) { // while (!isEmpty()) // dst.add(pop()); // } } //Ex4 : class CollectionTrucsSousMere{ List l; public void set(List l2){ l=l2; } //on veut pouvoir faire du set(ArrayList l2) //on veut pouvoir faire du set(ArrayList l2) } //on a besoin du ? car //- si on avait List l et set(List l2) alors on pourrai pas faire set(ArrayList l2) car List pas sous type de List //- si on générisait la class avec CollectionTrucsSousMere{ .. puis utiliser T partout}, alors on pourrait pas mettre FilleUn puis FilleDeux, il faudrait //fixer le type au début, en ce sens ? est plus souple