Chapitre VII Généricité. POO-L3 H. Fauconnier2 Chapitre VII 1. Principes généraux 2. Types génériques imbriqués 3. Types paramètres bornés 4. Méthodes.

Slides:



Advertisements
Présentations similaires
La programmation orientée objet avec Java L3-MIAGE Plan
Advertisements

1 Quelques précisions sur l'héritage. 2 Signification de super.f() appel à la méthode f() masquée super : désigne l'objet appelant comme s'il était de.
SI3 MAM3 Hydro Nathan Cohen Igor Litovsky Christophe Papazian
Au programme du jour …. Un peu plus de structures de données
La classe String Attention ce n’est pas un type de base. Il s'agit d'une classe défini dans l’API Java (Dans le package java.lang) String s="aaa"; // s.
Approfondissement du langage
Algorithme et programmation
Chapitre III Héritage (début)
Classes locales classes définies à l'intérieur d'un bloc de code,
IPA – Catherine Faron Zucke et Anne Marie Deryr. suite ordonnée d'éléments de taille variable ArrayList liste; liste = new ArrayList (); Ne peuvent contenir.
Introduction à la programmation (420-PK2-SL) cours 12 Gestion des applications Technologie de linformation (LEA.BW)
Les méthodes en java Une méthode est un regroupement d’instructions ayant pour but de faire un traitement bien précis. Une méthode pour être utilisée.
POO-L3 H. Fauconnier1 Chapitre IV 1. classe Object, clonage 2. interfaces 3. classes internes et imbriquées.
Langage Oriente Objet Cours 4.
Généricité (fin) collections…. GénéricitéPOO-L3 H. Fauconnier2 Chapitre VII 1. Principes généraux 2. Types génériques imbriqués 3. Types paramètres bornés.
POO-L3 H. Fauconnier1 Tableau et héritage Y[] yA=new Y[3]; X[] xA=yA; //ok xA[0]=new Y(); xA[1]=new X(); //non xA[1]=new Z(); //non Object XX[]int[] YZY[]Z[]
Premier cours (23 septembre). Cours programmation- orientée objet en Java Licence dinformatique Hugues Fauconnier
Chapitre VII Généricité. POO-L3 H. Fauconnier2 Chapitre VII 1. Principes généraux 2. Types génériques imbriqués 3. Méthodes génériques 4. Types paramètres.
Introduction au paradigme objet Concepts importants surcharge (overload) redéfinition (override) Définition d’une classe Définition des attributs.
Master 1 SIGLIS Java Lecteur Stéphane Tallard Chapitre 5 – Héritage, Interfaces et Listes génériques.
Présentation Structures de Données et TDA
Contrôle de types Les types en programmation Expressions de types Un contrôleur de types Equivalence de types Conversions de types Généricité.
IFT 6800 Atelier en Technologies d’information
1 IFT 6800 Atelier en Technologies dinformation Le langage de programmation Java chapitre 3 : Classes et Objects.
Chapitre 9 Les sous-programmes.
Cours du 22 novembre généricité. Chapitre VII Généricité.
Généricité. POO-L3 H. Fauconnier2 Chapitre VII 1. Principes généraux 2. Types génériques imbriqués 3. Méthodes génériques 4. Types paramètres bornés.
Chapitre III Héritage. POO-L3 H. Fauconnier2 Chapitre III: Héritage A) Extensions généralités Affectation et transtypage B) Méthodes Surcharge et signature.
Cours 4 Héritage (suite).
Cours 11 Threads. Chapitre X threads threadPOO-L3 H. Fauconnier3 Threads threads: plusieurs activités qui coexistent et partagent des données exemples:
Cours 8 (18 novembre 2011) exceptions. héritagePOO-L3 H. Fauconnier2 Tableau et héritage Y[] yA=new Y[3]; X[] xA=yA; //ok xA[0]=new Y(); xA[1]=new X();
COURS DE PROGRAMMATION ORIENTEE OBJET :
Java, les objets : tout de suite ! Rassembler, grouper les objets
IFT-2000: Structures de données Piles et files Dominic Genest, 2009.
Structures de données IFT-10541
99 Réutilisation du code grâce à l'héritage. 9-2 Objectifs À la fin de ce cours, vous serez capables de : Définir l'héritage Utiliser l'héritage pour.
2.1 - Historique Chapitre 2 : Introduction au langage C++
Objectifs À la fin de ce cours, vous serez capables de :
LIFI-Java 2004 Séance du Mercredi 22 sept. Cours 3.
La notion de type revisitée en POO
Cours 9 Exceptions (fin) Généricité. POO-L3 H. Fauconnier2 Chaînage d'exceptions  Une exception peut être causée par une autre.  il peut être utile.
11/04/ L'héritage Cours 7 Cours 7.
Cours 7 Classes locales Clonage Divers: tableaux.
Master 1 SIGLIS Java Lecteur Stéphane Tallard Les erreurs communes en Java.
Tutorat en bio-informatique
Les classes présenté par: RAHMOUNE RIME / ZEKRI SELMA.
Les classes et les objets Les données finales class A { … private final int n = 20 ; // la valeur de n est définie dans sa déclaration … } class A { public.
C# de plus près.  Ce sont globalement les mêmes que Java : ◦ Int(int16, int32), float, double, bool,…  Les classe « communes » sont également les mêmes.
Cours du 5 novembre.
Héritage H. Batatia. plan Notion (que signifie l’héritage) Ecriture en java Héritage multiple (interdit) Instanciation (partie propre et partie héritée)
Cours 4 (14 octobre) Héritage. Chapitre III Héritage.
Héritage Conception par Objet et programmation Java
Conception de Programmes - IUT de Paris - 1ère année Quelques éléments du langage C++ Les références La surcharge de fonctions Les fonctions «
Cours du 26 octobre  Classes internes  Clones POO-L3 H. Fauconnier1.
8PRO107 Éléments de programmation Les adresses et les pointeurs.
Généricité.
Philippe Gandy – 10 novembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Spécialisation covariante cours et TP. Plan  Introduction  Rappels théoriques  Définition de la covariance  Présentation du modèle servant d'exemple.
1 ALGORITHMIQUE AVANCEE IUT Vélizy – RT2 FA Laurent Marsan.
Introduction à la Programmation Orientée Objet H.GATI.
Chapitre 6 Les tests d ’ hypoth è se 2 – Les tests du  2 (chi 2)
Principes de l'orienté objet Jean-Jacques LE COZ.
Informatique 1A Langage C 6 ème séance 1. Objectifs de la séance 6  Allocation dynamique de mémoire  Application à la création de tableaux 2.
Chapitre X threads. threadPOO-L3 H. Fauconnier2 Threads  threads: plusieurs activités qui coexistent et partagent des données Exemples: pendant un chargement.
Informatique 2A Langage C 3 ème séance.
Cours de Langage C Les structures
INSCRIPTIONS SPORTIVES
JAVA et POO : Notion d'héritage
Transcription de la présentation:

Chapitre VII Généricité

POO-L3 H. Fauconnier2 Chapitre VII 1. Principes généraux 2. Types génériques imbriqués 3. Types paramètres bornés 4. Méthodes génériques

GénéricitéPOO-L3 H. Fauconnier3 Principes  Paramétrer une classe ou une méthode par un type:  une pile de X En java toute classe étant dérivée de Object, cela permet d'obtenir une forme de généricité mais sans contrôle des types  une pile d'Object La généricité en Java est un mécanisme "statique" assez complexe la généricité existe dans d'autres langages (exemple C++ et Ada) (mais de façon différente)

GénéricitéPOO-L3 H. Fauconnier4 Exemple: FileFile public class Cellule { private Cellule suivant; private E element; public Cellule(E val) { this.element=val; } public Cellule(E val, Cellule suivant){ this.element=val; this.suivant=suivant; } public E getElement(){ return element;} public void setElement(E v){ element=v; } public Cellule getSuivant(){ return suivant;} public void setSuivant(Cellule s){ this.suivant=s; }

GénéricitéPOO-L3 H. Fauconnier5 Suite class File { protected Cellule tete; protected Cellule queue; private int taille=0; public boolean estVide(){ return taille==0; } public void enfiler(E item){ Cellule c=new Cellule (item); if (estVide()) tete=queue=c; else{ queue.setSuivant(c); queue=c; } taille++; } //..

GénéricitéPOO-L3 H. Fauconnier6 suite public E defiler(){ if (estVide()) return null; Cellule tmp=tete; tete=tete.getSuivant(); taille--; return tmp.getElement(); } public int getTaille(){ return taille; }

GénéricitéPOO-L3 H. Fauconnier7 Usage Cellule cel=new Cellule (23); File fi=new File (); File fs=new File (); File fobj=new File (); String[] st={"zéro","un","deux", "trois","quatre","cinq"}; for(int i=0;i<st.length;i++){ fs.enfiler(st[i]); fi.enfiler(i); }

GénéricitéPOO-L3 H. Fauconnier8 Remarques  Une déclaration de type générique peut avoir plusieurs paramètres: Map  Contrôle de type fs.enfiler(4) est refusé à la compilation

Types génériques, pourquoi?  Vérification de type: Comparons: List myIntList = new LinkedList(); myIntList.add(new Integer(0)); Integer x = (Integer) myIntList.iterator().next(); Et: List myIntList = new LinkedList (); myIntList.add(new Integer(0)); x=myIntList.iterator().next(); POO-L3 H. Fauconnier9

Invocation et type paramètré public interface List { void add(E x); Iterator iterator(); } public interface Iterator { E next();boolean hasNext();} List pourrait "générer" (comme en C++) public interface IntegerList { void add(Integer x); Iterator iterator(); } Mais… une déclaration d'un type générique crée un vrai type (qui est compilé comme tout) et il n'y a pas de type pour List POO-L3 H. Fauconnier10

GénéricitéPOO-L3 H. Fauconnier11 Typage  Une invocation ne crée pas un nouveau type: (fs.getClass()==fi.getClass()) est vrai la classe est ici File il s'agit surtout d'un contrôle (effectué à la compilation) à l'exécution fi n'a plus aucune information sur quelle invocation a permis sa construction (erasure)

GénéricitéPOO-L3 H. Fauconnier12 Conséquences  Aucune instanciation n'est possible pour un type en argument Dans l'exemple: E v=new E(); est impossible Pas de tableau de E

GénéricitéPOO-L3 H. Fauconnier13 Exemple public E[] toArray(File f){ E[] tab=new E[f.getTaille()]; //non for(int i=0;i<f.getTaille();i++) tab[i]=f.defiler(); }  Comment construire un tableau sans connaître le type de base?  La classe Array et la méthode Array.newInstance() permettraient de résoudre ce problème (mais sans contrôle de type) Array  On peut aussi utiliser la classe Object. Object

GénéricitéPOO-L3 H. Fauconnier14 Object public static Object[] toArray(File f){ Object[] tab=new Object[f.getTaille()]; for(int i=0;i<f.getTaille();i++) tab[i]=f.defiler(); return tab; } mais on perd l'avantage du contrôle de type.

GénéricitéPOO-L3 H. Fauconnier15 Contrôle du type  Pourtant, on peut passer un objet d'un type paramètré à une méthode.  Comment se fait le passage des paramètres? le compilateur passe le type le plus général ( Object ) et utilise le cast pour assurer le contrôle du typage.

GénéricitéPOO-L3 H. Fauconnier16 Chapitre VII 1. Principes généraux 2. Types génériques imbriqués 3. Types paramètres bornés 4. Méthodes génériques

GénéricitéPOO-L3 H. Fauconnier17 Types génériques imbriqués public class FileSimpleChainageb { public class Cellule{ private Cellule suivant; private E element; public Cellule(E val) { this.element=val; } public Cellule(E val, Cellule suivant){ this.element=val; this.suivant=suivant; } public E getElement(){ return element; } public void setElement(E v){ element=v; }//...

GénéricitéPOO-L3 H. Fauconnier18 Suite public Cellule getSuivant(){ return suivant; } public void setSuivant(Cellule s){ this.suivant=s; } protected Cellule tete; protected Cellule queue; private int taille=0; public boolean estVide(){ return taille==0; } public int getTaille(){ return taille; }

GénéricitéPOO-L3 H. Fauconnier19 Fin… public void enfiler(E item){ Cellule c=new Cellule(item); if (estVide()) tete=queue=c; else{ queue.setSuivant(c); queue=c; } taille++; } public E defiler(){ if (estVide()) return null; Cellule tmp=tete; tete=tete.getSuivant(); taille--; return tmp.getElement(); }

GénéricitéPOO-L3 H. Fauconnier20 Chapitre VII 1. Principes généraux 2. Types génériques imbriqués 3. Types paramètrés bornés 4. Méthodes génériques

Sous-typage List ls = new ArrayList (); List lo = ls; //1 lo.add(new Object()); //2 String s = ls.get(0); //3 ! Si A est une extension de B, F n'est pas une extension de F : //1 est interdit Pour les tableaux: si A est une extension de B un tableau de A est une extension de tableau de B. //1 est autorisé, mais ensuite //2 est interdit POO-L3 H. Fauconnier21

Joker '?' void printCollection(Collection c) { for (Object e : c) { System.out.println(e);} } Ne fonctionne pas avec une Collection (n'est pas une extension de Collection ) Une collection de n'importe quoi ('?') void printCollection(Collection c) { for (Object e : c){ System.out.println(e);} } est possible (n'importe quoi est un objet). Mais Collection c = new ArrayList (); c.add(new Object()); // erreur compilation POO-L3 H. Fauconnier22

Mais  Ce n'est pas suffisant… On peut vouloir borner le type en paramètre: comparable est une interface générique qui indique la possibilité de comparer des objets class valeur implements Comparable {..} Une SortedCollection est construite sur des classes E qui implémentent Comparable d'où: interface SortedCollection >{} POO-L3 H. Fauconnier23

GénéricitéPOO-L3 H. Fauconnier24 Exemple static double somme(List l){ double res=0.0; for(Number n:l) res+=n.doubleValue(); return res; } public static void main(String[] st){ List l= new ArrayList (); for(int i=0;i<10;i++)l.add(i); double s=somme(l); //incorrect }

GénéricitéPOO-L3 H. Fauconnier25 Type paramètré borné  Au moins un number:  List une liste constituée de n'importe quel type dérivé de Number static double somme2(List l){ double res=0.0; for(Number n:l) res+=n.doubleValue(); return res; }

GénéricitéPOO-L3 H. Fauconnier26 Types bornés  List indique que le type doit au moins être un Number (tout type qui dérive de Number ) borné par le bas : au moins un Number  On peut aussi imposer que le type soit une superclasse d'un autre type List borné par le haut : au plus un Integer (super- classe de Integer )  ( est une abréviation de )

Types paramètrés bornés  X := Y Y doit être d'un type qui est une extension de la classe de X (? extends X) X doit être d'un type qui est une super classe (=restriction) de Y (? super Y) POO-L3 H. Fauconnier27

GénéricitéPOO-L3 H. Fauconnier28 Sous-typage  List est une super classe de List Et:  List List  List List

GénéricitéPOO-L3 H. Fauconnier29 Types paramètrés bornés  Exemple: SortedCollection est composée d'éléments du type E et ces éléments peuvent être comparés.  Mais > est trop fort: la comparaison n'est pas obligée de se faire entre éléments de E, elle peut aussi se faire entre des éléments qui peuvent être affectés par des E: si E extends Comparable a fortiori on peut comparer les éléments de E  il suffit que E extends Comparable pour T égal à E ou T superclasse de E d'où: >

GénéricitéPOO-L3 H. Fauconnier30 Mais attention File str=new File (); str.enfiler("un"); provoque une erreur à la compilation (? peut être n'importe quel type) enfiler(capture of ?) in generique.File cannot be applied to (java.lang.String) de même que: File num=new File (); num.enfiler(Integer.valueOf(12)); en effet File peut être par exemple une File d'un type dérivé de Number. Par contre: File num=new File (); num.enfiler(Integer.valueOf(12)); est correct (? superclasse de Number)

GénéricitéPOO-L3 H. Fauconnier31 Quelques explications  ? peut correspondre à n'importe quelle classe enfiler(a) où a est de classe A ne peut fonctionner que si la classe correspondant à ? est une super-classe de A  de même ? dans ne peut fonctionner car si ? est Y extension de X il faut un paramètre d'une classe dérivée de Y  par contre ? dans ne pouvant correspondre qu'à une classe "avant" X (une superclasse de X), tout Z dérivé de X fonctionne

GénéricitéPOO-L3 H. Fauconnier32 Mais  inversement pour la valeur retournée: File n=new File (); n.defiler(); defiler() doit retourner une valeur qui peut être affectée à ? : pas de problème idem pour qui doit retourner une valeur d'une extension de Number mais pour: File n=new File (); Number m=n.defiler(); ? est une superclasse de Number et ne peut pas toujours être affecté à un Number

GénéricitéPOO-L3 H. Fauconnier33 Chapitre VII 1. Principes généraux 2. Types génériques imbriqués 3. Types paramètres bornés 4. Méthodes génériques

GénéricitéPOO-L3 H. Fauconnier34 Méthodes génériques  Supposons que l'on veuille convertir en tableau une File de E on a vu précédemment que l'on ne pouvait ni instancier un objet E ni créer un tableau de E on peut cependant passer un tableau de la taille appropriée à une méthode qui retourne ce tableau:

GénéricitéPOO-L3 H. Fauconnier35 enTableau1 public E[] enTableau1(E[] tab){ Object[] tmp = tab; int i=0; for(Cellule c= tete; c != null && i< tab.length; c=c.getSuivant()) tab[i++] = c.getElement(); return tab; }  enTableau1 est une nouvelle méthode de File: File fs=new File (); String[] u; u=fs.enTableau1(new String[fs.getTaille()]);

GénéricitéPOO-L3 H. Fauconnier36 enTableau  Mais, il faut que le tableau passé en paramètre soit un tableau de E, alors qu'un tableau d'une super-classe de E devrait fonctionner (si F est une superclasse de E un tableau de F peut contenir des objets E). avec une méthode générique:

GénéricitéPOO-L3 H. Fauconnier37 enTableau public T[] enTableau(T[] tab){ Object[] tmp = tab; int i=0; for(Cellule c= tete; c != null && i< tab.length; c=c.getSuivant()) tmp[i++] = c.getElement(); return tab; }  la déclaration impose que le type du tableau retourné soit du type du tableau de l'argument  Notons que tmp est un tableau d' Object ce qui est nécessaire pour le getSuivant  Notons que normalement il faudrait que T soit une superclasse de E (à l'exécution il peut y avoir une erreur).  Notons enfin que ' T ' ne sert pas dans le corps de la méthode.

GénéricitéPOO-L3 H. Fauconnier38 Remarque public T[] enTableaubis(T[] tab){ int i=0; for(Cellule c= tete; c != null && i< tab.length; c=c.getSuivant()) tab[i++] = (T)c.getElement(); return tab; }  provoque un warning "Cellule.java uses unchecked or unsafe operations".  (l'"effacement" ne permet pas de vérifier le type)

GénéricitéPOO-L3 H. Fauconnier39 Avec Reflection…  Une autre solution peut être si on veut créer un vrai tableau est d'utiliser Array.newInstance de la classe: java.lang.reflect

GénéricitéPOO-L3 H. Fauconnier40 Exemple avec ReflectionReflection public E[] enTableau2(Class type){ int taille = getTaille(); E[] arr=(E[])Array.newInstance(type,taille); int i=0; for(Cellule c= tete; c != null && i< taille; c=c.getSuivant()) arr[i++] = c.getElement(); return arr; }  on crée ainsi un tableau de "E"  "unchecked warning": le cast (E[]) n'a pas le sens usuel  pour fs déclaré comme précédemment on aura: String[] u=fs.enTableau2(String.class); //ok Object[] v=fs.enTableau2(Object.class); //non  car le type doit être exact

GénéricitéPOO-L3 H. Fauconnier41 Avec une méthode générique public T[] enTableau3(Class type){ int taille = getTaille(); T[] arr=(T[])Array.newInstance(type,taille); int i=0; Object[] tmp=arr; for(Cellule c= tete; c != null && i< taille; c=c.getSuivant()) tmp[i++] = c.getElement(); return arr; }

GénéricitéPOO-L3 H. Fauconnier42 Inférence de type  Comment invoquer une méthode générique?  Exemple: static T identite(T obj){ return obj; }

GénéricitéPOO-L3 H. Fauconnier43 Invocations  On peut explicitement préciser le type: String s1="Bonjour"; String s2= Main. identite(s1);  Mais le compilateur peut trouver le type le plus spécifique: String s1=identite("Bonjour");  On aura: Object o1=identite(s1); //ok Object o2=identite((Object)s1); //ok s2=identite((Object) s1); //non!!! s2=(String)identite((Object) s1);//ok

GénéricitéPOO-L3 H. Fauconnier44 Comment ça marche?  Mécanisme de l'effacement ("erasure")  Pour chaque type générique il n'y a qu'une classe: Cellule et Cellule ont la même classe  Effacement: Cellule -> Cellule  Cellule est un type brut Pour une variable type:  -> Object  -> Number  Le compilateur remplace chaque variable type par son effacement

GénéricitéPOO-L3 H. Fauconnier45 Comment ça marche?  Si le résultat de l'effacement du générique ne correspond pas à la variable type, le compilateur génère un cast: par effacement le type variable de File est Object pour un "defiler" sur un objet File le compilateur insère un cast sur String

GénéricitéPOO-L3 H. Fauconnier46 Comment ça marche?  A cause de l'effacement, rien de ce qui nécessite de connaître la valeur d'un argument type n'est autorisé. Par exemple: on ne peut pas instancier un paramètre type: pas de new T() ou de new T[] on ne peut pas utiliser instanceof pour une instance de type paramétrée on ne peut pas créer de tableau sur un type paramétré sauf s'il est non borné: new List [10] est interdit mais new List [10] est possible.

GénéricitéPOO-L3 H. Fauconnier47 Comment ça marche?  les "cast" sont possibles mais n'ont pas la même signification que pour les types non paramétrés: le cast est remplacé par un cast vers le type obtenu par effacement et génère un "unchecked warning" à la compilation. Exemple:  on peut caster le paramètre File vers un File pour un enfiler (ce qui génère le warning)  A l'exécution si le type effectif est File cela passe… mais le defiler provoquera un ClassCastException.

GénéricitéPOO-L3 H. Fauconnier48 Comment ça marche?  Exemple: List l=new ArrayList (); Object o=identite(l); List l1=(List )o;// warning List l2=(List)o;//warning List l3=(List) o; //ok List l4=(List )o; //ok

GénéricitéPOO-L3 H. Fauconnier49 Application: surcharge  avoir la même signature s'étend aux méthodes avec variables types  même signature pour des variables types = même type et même borne (modulo bien sûr renommage!)  signatures équivalentes par annulation: mêmes signatures où l'effacement des signatures sont identiques

GénéricitéPOO-L3 H. Fauconnier50 Surcharge class Base { void m(int x){}; void m(T t){}; void m(String s){}; void m(N n){}; void m(File q){}; } Après effacement: m(int) m(Object) m(String) m(Number) m(File)

GénéricitéPOO-L3 H. Fauconnier51 Et héritage…  exemple: class D extends Base { void m(Integer i){} //nouveau void m(Object t){} // redéfinit m(T t) void m(Number n){} // redéfinit m(N n) }