1 / 12

Java : Les types génériques (<T>)

LES TYPES GENERIQUES :. Java : Les types génériques (<T>). Introduction (diapo 2). Déclaration d’un type générique (3) 1re déclaration simple <T>, <?> (3) 2e décl. : <T extends xxx>, <? extends xxx> (5) 3e décl. : <T super xxx>, <? super xxx> (7)

kert
Télécharger la présentation

Java : Les types génériques (<T>)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. LES TYPES GENERIQUES : Java : Les types génériques (<T>) • Introduction (diapo 2) • Déclaration d’un type générique (3) • 1re déclaration simple <T>, <?> (3) • 2e décl. : <T extends xxx>, <? extends xxx> (5) • 3e décl. : <T super xxx>, <? super xxx> (7) • Déclaration multiple <T,U,…> (8) • Conventions de nommage(9) • Déclaration d’une méthode générique (10) Cours JAVA / Y.Laborde

  2. <T> : Introduction Voir The Java Tutorials : http://java.sun.com/docs/books/tutorial/java/generics/gentypes.html • Présenté dans J2SE 5.0 (également appelé Java SE 6), ce perfectionnement du système de type longtemps attendu permet : • de générer de multiples déclarations de types, de méthodes ou de constructeurs à l’aide d’une seule déclaration générique, • Ex: public class ArrayList<E> … {… public boolean add(E e) {…} public E get(int index) {…} …} • de générer de multiples déclarations de variables sur la base d’un schéma de type générique inféré à la compilation. • Ex: ArrayList<Domino> laPioche = new ArrayList<Domino>; • ArrayList<Joueur> lesJoueurs = new ArrayList<Joueur>; • L’avantage qui en résulte est de permettre de disposer d’ensembles dont le type des éléments est contraint. Le Java Collections Framework utilise abondamment des classes déclarées comme des types génériques. Malgré une complexité apparente, ces classes sont très simples d’emploi. Ex: • public class ArrayList<E>extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable • public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> • public interface List<E> extends Collection<E> • public interface Collection<E>extends Iterable<E> • public interface Iterable<T> Remarques: les types génériques de Java sont proches des Templates du C++ mais, par certains côtés, ils présentent d’importantes différences qu’il est nécessaire d’assimiler. Cours JAVA / Y.Laborde

  3. <T> : Déclaration d’un type générique (1) 1. Première SYNTAXE SIMPLE pour déclarer un type générique, comme classe ou interface : ["public" | "private"] "class"<Nom_de_base>'<' <Lettre>'>’ ["extends" …] ["implements" …] {…} ou ["public" | "private"] "interface"<Nom_de_base>'<' <Lettre>'>’ ["extends" …] {…} • Exemple : • /** • * Generic version of the Box1 class. • */ • public class Box1<T> { • privateT t; • public voidadd (T t) { this.t = t; } • public Tget ( ) { return this.t; } • } Pour instancier un objet : new Box1<Integer>( ) ou new Box1<Boolean>( ) soit avec une déclaration de référence : Box1<Integer> integerBox1 = new Box1<Integer>( ); Box1<Boolean> booleanBox1 = new Box1<Boolean>( ); Exemple d’utilisation : public class Box1Demo{ public static void main (String[] args) { Box1<Number> numberBox1 = new Box1<Number>( ); numberBox1.add (new Integer (10)); Number someNumber = numberBox1.get ( ); // no cast! System.out.println ("Box1<Number> numberBox1 => " + someNumber); } } OUTPUT: Box1<Number> numberBox1 => 10 Cours JAVA / Y.Laborde

  4. <T> : Déclaration d’un type générique (1) • public class Box1<T> { • private T t; public void add (T t) { this.t = t; } public T get ( ) { return t; } • } Il est aussi permis de déclarer des références à des types inconnus (avant inférence) ! On utilise alors un caractère jocker (wildcard) qui permet de désigner toutes les sortes de Box1<T> Autre exemple d’utilisation : public class Box1Demo{ public static void main(String[] args) { Box1<Number> numberBox1 = new Box1<Number>( ); numberBox1.add (new Integer (10)); showGenericBox1 (numberBox1); } V1: public static void showGenericBox1 (Box1<?> someBox1) { Number someNumber = (Number)someBox1.get ( ); // cast needed! System.out.println ("Box1<?> someBox1 => " + someNumber ); } V2: public static void showGenericBox1 (Box1<?> someBox1) { System.out.println ("Box1<?> someBox1 => " + someBox1.get ( )); // no cast! } } Mais on ne peut retrouver le type de <T> qu’à l’aide d’un cast ! Cette technique doit donc être évitée ! En effet, si <T> n’est pas un nombre, une exception sera levée !!! OUTPUT: Box1<?> someBox1 => 10 OUTPUT: Box1<?> someBox1 => 10 On peut tout de même s’affranchir du cast ! Mais il n’est alors possible d’utiliser l’objet de type inconnu <T> que comme un Object ! ICI: le compilateur traduit l’usage de someBox1.get ( ) en someBox1.get ( ).toString() Cours JAVA / Y.Laborde

  5. <T> : Déclaration d’un type générique (2) • 2. Deuxième syntaxe pour déclarer un type générique, comme classe ou interface : • ["public" | "private"] "class"<Nom_de_base>'<' <Lettre>"extends" <Type ou Interface>'>’ • ["extends" …] ["implements" …] {…} • ou ["public" | "private"] "interface"<Nom_de_base>'<' <Lettre>"extends" <Type ou Interface>'>’ • ["extends" …] {…} • où "extends" a un sens général qui convient aussi bien pour « extends » que pour « implements ». • Exemple : • public interfaceIAnimal { • public void setName (String name); • public String getName (); • } • /** • * Generic version of the Box2 class. • */ • public classBox2<T extends IAnimal> { • private T t; • public void add (T t) { this.t = t; } • public T get ( ) { return this.t; } • } • public abstract classAnimalimplementsIAnimal { • private String name; • // Constructor • public Animal(String name) { this.name = name; } • // override • public String toString ( ) { return this.name; } • // IAnimal method implementations • public String getName ( ) { return this.name; } • public void setName (String name) { this.name = name; } • } • public classLionextendsAnimal { • public Lion(String name) { super(name); } • } • public class Butterfly extends Animal { • public Butterfly(String name) { super(name); } • } Cours JAVA / Y.Laborde

  6. <T> : Déclaration d’un type générique (2) • public classBox2Demo { • public static void main (String[] args) { • Box2<Lion> lionBox2 = new Box2<Lion>( ); • lionBox2.add (new Lion ("Simba")); • Box2<Butterfly> butterflyBox2 = new Box2<Butterfly>( ); • butterflyBox2.add (new Butterfly ("Citronade")); • Box2Demo.showAnimalInBox2 (lionBox2); // Show animal from a Box2<Lion> • Box2Demo.showAnimalInBox2 (butterflyBox2); // Show animal from a Box2<Butterfly> • } • public static void showAnimalInBox2 (Box2<? extends IAnimal> animalBox2) { • IAnimal someAnimal = animalBox2.get( ); // no cast! • System.out.println ( "Box2<? extends IAnimal> animalBox2 => " • + someAnimal.getName( ) + " : “ + someAnimal.getClass( ).getName( ) ); • } • } Ajout d’un Lion dans une Box2<Lion> Ajout d’un Papillon dans une Box2<Butterfly> • OUTPUT: • Box2<? extends IAnimal> animalBox2 => Simba : samplesgenerics.Lion • Box2<? extends IAnimal> animalBox2 => Citronade : samplesgenerics.Butterfly La méthode utilise un type générique avec un caractère jocker (wildcard) pour recevoir toutes les sortes de Box2<T> où T implemente au moins un IAnimal Cours JAVA / Y.Laborde

  7. <T> : Déclaration d’un type générique (3) • 3. Troisième syntaxe pour déclarer un type générique, comme classe ou interface : • ["public" | "private"] "class"<Nom_de_base>'<' <Lettre>"super" <Type ou Interface>'>’ • ["extends" …] ["implements" …] {…} • ou ["public" | "private"] "interface"<Nom_de_base>'<' <Lettre>"super"<Type ou Interface>'>’ • ["extends" …] {…} • où "super" a un sens général qui convient aussi bien pour les classes que les interfaces. Le type générique <T extends IAnimal> signifie que le type inféré doit relever AU MINIMUM d’une sorte de IAnimal, c-à-d qu’il doit implémenter l’interface IAnimal ou ses sous-interfaces. Le type générique <T extends Animal> signifie que le type inféré doit relever AU MINIMUM d’une sorte de Animal, c-à-d qu’il doit être de la classe Animal ou de l’une de ses sous-classes. D’une manière équivalente, le type générique <T super Animal> signifie que le type inféré doit relever AU MAXIMUM d’une sorte de Animal, c-à-d qu’il doit être de la classe Animal ou de l’une de ses super-classes. De plus, l’usage d’un caractère jocker est permis comme dans : <? extends Animal> ou <? super Animal>. Cours JAVA / Y.Laborde

  8. <T> : Déclaration multiple Un type générique peut être déclaré à l’aide de multiples paramètres de types génériques. Mais chacun doit être unique à l’intérieur de sa déclaration de classe ou d’interface. La déclaration de Box<T,U> est correcte. Par contre, la déclaration de Box<T,T> génèrera une erreur sur la seconde occurrence de T. • Exemple : • /** • * Generic version of the Box3 class. • */ • public class Box3< T , U > { • privateT t; • privateU u; • public voidaddT (T t) { this.t = t; } • public TgetT ( ) { return this.t; } • public voidaddU (U u) { this.u = u; } • public UgetU ( ) { return this.u; } • } Cours JAVA / Y.Laborde

  9. <T> : Type générique - Conventions Conventions usuelles de nommage du paramètre de type (Java SE API) : Par convention, les noms des paramètres de type sont de SIMPLES LETTRES en MAJUSCULE. Sans cette convention, il serait très difficile de différencier un type variable du nom d’une classe ou d’une interface ordinaire. Les noms les plus communément utilisés dans l’API Java sont : Cours JAVA / Y.Laborde

  10. <T> : Déclion de méthode générique (1) 1. Première SYNTAXE SIMPLE pour déclarer une méthode générique : ["public" | … | "private"] ‘ <' <Lettre>'>' <Type_retourné><Nom_de_méthode> '('[<liste de paramètres formels utilisant le type générique>] ')' { <corps de la méthode utilisant le type générique> } • Exemple simple : • /** • * Generic version of the Box4 class. • */ • public class Box4<T> { • privateT t; • public voidadd (T t) { this.t = t; } • public Tget ( ) { return this.t; } • public <U> void inspectBox4 ( U u ) { • System.out.println ( "U: " + u.getClass().GetName() ); • System.out.println ( "T: " + t.getClass().GetName() ); • } • } • Exemple d’application : • public class Box4Demo { • public static void main (String[] args) { • Box<Integer> integerBox • = new Box<Integer>( ); • integerBox.add (new Integer(10)); • integerBox.inspect Box4 ("some text"); • } • } • OUTPUT: • T: java.lang.Integer • U: java.lang.String • OUTPUT: • T: java.lang.Integer • U: java.lang.String Cours JAVA / Y.Laborde

  11. <T> : Déclion de méthode générique (2) • public class CageDemo { • public static void main (String[] args) { • // Table des noms de lions • String[] lionNames = {"Mufasa","Simba","Nala","Scar"}; • // Créer une liste de lions (vide) • List<Lion> listLions = new ArrayList<Lion>( ); • // Remplir la liste de lions en instanciant des lions • // par itération de la table des noms de lions • for(String lionName : lionNames) • { listLions.add (new Lion(lionName)); } • // Créer une liste de cages de lion (vide) • List<Cage<Lion>> listCages = new ArrayList<Cage<Lion>>( ); • // n : nombre aléatoire dans [0,nombre de lions[ • int n = (int)(Math.random()*lionNames.length); • // Ajouter n cages de lion (vides) dans la liste de cages • for ( int i = 0 ; i <= n ; i++) • { listCages.add (new Cage<Lion>( )); } • // Remplir toutes les cages de la liste de cages • // avec un même lion obtenu aléatoirement • Cage.<Lion>fillBoxes (listCages, listLions.get(n)); • // Afficher le contenu de la liste de cages • System.out.println (listCages); • } • } Exemple plus réaliste de déclaration d’une méthode générique : • /** • * Generic version of the Cage class. • */ • public class Cage<T> { • private T t; • public void add (T t) { this.t = t; } • public T get ( ) { return this.t; } • // Remplissage des cages d'une liste de cages • // avec un objet u • public static <U>// => méthode générique • void fillBoxes (List<Cage<U>> cages, U u) { • // Itérer sur les cages de la liste de cages • for (Cage<U> cage : cages) • // Ajouter l'objet u dans la cage • { cage.add (u); } • } • // override • public String toString ( ) • { return "Cage(" + this.t.toString ( ) + ")"; } • } • Méthode générique • Invocation de la méthode générique statique • (<Lion> est optionnel) • OUTPUT: [Cage(Mufasa)] • ou [Cage(Simba), Cage(Simba)] • ou etc. QUEL EST L’AFFICHAGE PRODUIT ? Cours JAVA / Y.Laborde

  12. Java : Les types génériques (<T>) Vous pouvez compéter cette formation à l’aide du tutoriel Java : http://java.sun.com/docs/books/tutorial/java/generics/gentypes.html ou (plus avancé) http://java.sun.com/docs/books/tutorial/extra/generics/index.html Cours JAVA / Y.Laborde

More Related