Vous êtes sur la page 1sur 50

Algorithmique et Programmation

Objet
(APO)
L2MI Informatique
Semestre 4
Cours 1 : plan
G en ericit e
Classes g en eriques
M ethodes g en eriques
Instanciations avec jokers
2
G en ericit e
3
D enition
Une classe peut etre param etr ee avec des
valeurs.
La g en ericit e permet de param etrer du code
avec des types de donn ees.
Exemple :
class ArrayList<T>
dont le code est param etr e par un type T
Pour lutiliser il faut passer un type en
argument :
new ArrayList<Employe>()
4
Pourquoi la g en ericit e
Une collection dobjets ne contient le plus
souvent quun seul type dobjet : liste
demploy es, liste de livres, liste de chanes de
caract ` eres, etc.
Mais sans la g en ericit e les el ements des
collections doivent etre d eclar es de type Object.
Il est impossible dindiquer quune collection ne
contient quun seul type dobjet, comme on le
fait avec les tableaux (par exemple String[])
5
Exemple de code non g en erique
Soit une classe ArrayList qui impl emente une
liste en utilisant un tableau.
Elle contient les m ethodes :
boolean add(Object o)
Object get(int i)
6
Exemple de code non g en erique
ArrayList employes = new ArrayList();
Employe e = new Employe("Dupond");
employes.add(e);
. . . // On ajoute dautres employ es
for(int i = 0; i < employes.size(); i++) {
System.out.println(
((Employe) employes.get(i)).getNom());
}
Le

casting

est n ecessaire pour pouvoir utiliser


getNom().
7
Autre exemple (probl ematique)
ArrayList employes = new ArrayList();
Employe e = new Employe("Dupond");
employes.add(e);
. . . // On ajoute dautres employ es
// On ajoute un livre au milieu des employes
Livre livre = new Livre(...);
employes.add(livre);
for (int i = 0; i < employes.size(); i++) {
System.out.println(
((Employe) employes.get(i)).getNom());
}
8
Cons equences
Il est impossible dindiquer quune liste ne
contient que des instances dun certain type.
Certaines erreurs ne peuvent etre rep er ees qu ` a
lex ecution et non pas ` a la compilation.
Il faut sans arr et caster les el ements pour
pouvoir utiliser les m ethodes qui ne sont pas
dans Object.
Si un objet contenu dans les collections nest
pas du type attendu, on a une erreur ` a
lex ecution mais pas ` a la compilation.
9
Collections ` a type particulier
Si on veut eviter ces probl ` emes ( eviter les casts
et v erier les types ` a la compilation), il faut
ecrire un code diff erent pour chaque collection
dun type particulier
Par exemple, il faut ecrire une classe ListInteger
et une classe ListEmploye.
Ce qui revient ` a ecrire plusieurs fois la m eme
chose, en changeant seulement les types.
Ou alors, ecrire des codes g en eriques.
10
G en ericit e
La g en ericit e permet de param etrer une classe
ou interface avec un ou plusieurs types de
donn ees.
On peut par exemple donner en param` etre le
type des el ements dun Arraylist :
ArrayList<E>
E est un param` etre de type formel (ou plus
simplement param` etre de type) ou variable de
type.
E sera remplac e par un argument de type pour
typer des expressions ou cr eer des objets :
ArrayList<Integer> l = new ArrayList<Integer>();
11
G en ericit e (2)
ArrayList<E> est un type g en erique (plus
exactement une classe g en erique).
ArrayList<Employe> est une instanciation du
type g en erique ArrayList<E>; cest un type
param etr e concret (plus exactement une classe
param etr ee) dont largument de type est
Employe.
La g en ericit e permet d ecrire des collections
dont tous les el ements ont le m eme type, sans
avoir ` a r ep eter plusieurs fois le m eme code en
v eriant le typage d` es la compilation en evitant
les casts ` a lex ecution.
12
Extraits de la classe ArrayList
public class ArrayList<E>
extends AbstractList<E>{
public ArrayList() // pas ArrayList<E>() !
public boolean add(E element)
public E get(int index)
public E set(int index, E element)
}
13
Utilisation dun ArrayList param etr e
ArrayList<Employe> employes = new ArrayList<Employe>();
Employe e = new Employe("Dupond");
employes.add(e);
// On ajoute dautres employ es
...
for (int i = 0; i < employes.size(); i++) {
System.out.println(employes.get(i).getNom());
}
14
Erreur d etect ee ` a la compilation
ArrayList<Employe> employes =
new ArrayList<Employe>();
Employe e = new Employe("Dupond");
employes.add(e);
// On ajoute dautres employ es
...
// Ajoute un livre au milieu des employ es
Livre livre = new Livre(...);
employes.add(livre); // Erreur de compilation
15
Quelques d enitions
Type g en erique : une classe ou une interface
param etr ee par une section de param` etres de la
forme <T1, T2, . . ., Tn>.
Les Ti sont les param` etres de type formels.
Ils repr esentent des types inconnus au moment
de la compilation du type g en erique.
On place la liste des param` etres ` a la suite du
nom de la classe ou de linterface : List<E>
Map<K,V>.
16
O` u peuvent apparatre les
param` etres de type ?
Dans le code du type g en erique, les param` etres
de type formels peuvent etre utilis es comme les
autres types pour d eclarer des variables, des
param` etres, des tableaux ou des types retour
de m ethodes :
E element;
E[] elements;
17
O` u peuvent apparatre les
param` etres de type ? (2)
On peut caster avec un param` etre de type ; ca
revient ` a caster avec le type qui contraint le
param` etre de type (ou avec Object si le
param` etre de type nest pas contraint).
Un tel cast provoquera un avertissement du
compilateur (car pas s ur).
18
O` u peuvent apparatre les
param` etres de type ? (3)
Ils ne peuvent etre utilis es pour cr eer des objets
ou des tableaux, ni comme super-type dun
autre type :
pas de

new E()

pas de

new E[10]

pas de

class C extends E

On ne peut utiliser un param` etre de type ` a


droite de instanceof : pas de

x instanceof E

.
19
Types des arguments de type
Les arguments de type peuvent etre des
classes, m eme abstraites, ou des interfaces ;
par exemple
new ArrayList<Comparable>
Ils peuvent m eme etre des param` etres de type
formels ; par exemple :
public class C<E> {
...
f = new ArrayList<E>();
...
}
Un argument de type ne peut pas etre un type
primitif.
20
Arguments de type abstraits
On peut utiliser un argument de type abstrait
(classe abstraite, interface) pour instancier une
classe g en erique ; si EmployeI est une interface,
on peut ecrire :
List<EmployeI> l = new ArrayList<EmployeI>();


Evidemment, il faudra remplir cette liste avec
des employ es

concrets

.
21
Cr eation dune instance de classe
param etr ee
Au moment de la cr eation dune classe
param etr ee, on indique le type de la collection
en donnant un argument de type pour chaque
param` etre de type formel
ArrayList<String> liste = new ArrayList<String>();
Map<String,Integer> map = new Map<String,Integer>();
22
Utilisation des types g en eriques
On peut utiliser les types g en eriques comme
sur-type (classe m` ere ou interface).
Exemple :
public class C<P> extends M<P>
Sinon, on ne peut utiliser un param` etre de type
que dans une classe g en erique param etr ee par
ce param` etre de type.
23
Classe interne dune classe
g en erique
Si une classe interne non static dune classe
g en erique utilise un param` etre de type, il ne faut
pas faire lerreur de mettre le param` etre de type
dans la d enition de la classe interne.
En effet, ce param` etre de type serait consid er e
comme un param` etre de type diff erent de celui
de la classe englobante.
24
Exemple
Ceci est une erreur :
public class Cache<K,T> {
private class EntreeCache<T> {
...
Il faut ecrire :
public class Cache<K,T> {
privateclass EntreeCache {
...
Et il est possible dutiliser T dans le code de la
classe EntreeCache.
25
M ethode g en erique
Comme une classe ou une interface, une
m ethode (ou un constructeur) peut etre
param etr ee par un ou plusieurs types.
Une m ethode g en erique peut etre incluse dans
un classe non g en erique, ou dans une classe
g en erique (si elle utilise un param` etre autre que
les param` etres de type formels de la classe).
26
Syntaxe
Une liste de param` etres apparat dans len-t ete
de la m ethode pour indiquer que la m ethode ou
le constructeur d epend de types non connus au
moment de l ecriture de la m ethode :
<T1, T2, ... > ... m(...)
Exemple de linterface Collection<E> :
public abstract <T> T[] toArray(T[] a)
27
Instanciation dune m ethode
g en erique
On peut appeler une m ethode param etr ee en la
pr exant par le (ou les) type qui doit remplacer
le param` etre de type : <String>m().
Mais le plus souvent le compilateur peut faire
une inf erence de type (

deviner

le type)
dapr ` es le contexte dappel de la m ethode.
28
Inf erence de type
On appelle alors la m ethode param etr ee sans la
pr exer par un argument de type :
ArrayList<Personne> liste;
. . .
Employe[] res = liste.toArray(new Employe[0]);
// Inutile de pr efixer par le type :
// liste.<Employe>toArray(...);
29
Inf erence de type (2)
Parfois, cest un peu plus complexe pour le
compilateur :
public <T> T choose(T a, T b) { ... }
...
Number n = choose(new Integer(0), new Double(0.0));
Le compilateur inf ` ere Number qui est la

plus
proche

super-classe de Integer et Double.


30
Sous-typage et g en ericit e
Puisque que ArrayList<E> impl emente
List<E>, ArrayList<E> est un sous-type de
List<E>.
Ceci est vrai pour tous les types param etr es
construits ` a partir de ces 2 types.
Par exemple, ArrayList<Personne> est un
sous-type de List<Personne> ou
ArrayList<Integer> est un sous-type de
List<Integer>.
31
Sous-typage pour les types
param etr es
Mais attention : si B h erite de A, les classes
ArrayList<B> et ArrayList<A> nont aucun lien
de sous-typage entre elles.
Exemple : ArrayList<Integer> nest pas un
sous-type de ArrayList<Number>! ! (Number
est la classe m` ere de Integer).
32
Raison
Si ArrayList<B> etait un sous-type de
ArrayList<A>, le code suivant compilerait :
// ce code ne compile pas!!
ArrayList<A> la = new ArrayList<B>;
la.add(new A());
Quel serait le probl ` eme ?
Ce code autoriserait lajout dans un
ArrayList<B> dun el ement qui nest pas un B!
33
Cons equences
Une m ethode sort(ArrayList<Number> aln) qui
trie un ArrayList<Number> ne peut etre
appliqu ee ` a un ArrayList<Integer>.
De m eme, linstruction suivante est interdite :
ArrayList<Number> l = new ArrayList<Integer>();
34
Exemple de probl ` eme
public static void
printElements(ArrayList<Number> liste) {
for(Number n : liste) {
System.out.println(n.intValue());
}
}
ArrayList<Double> liste = new ArrayList<Double>();
...
printElements(liste); // Ne compile pas !
35
Probl ` eme pour la r eutilisation
Ceci nuit evidemment beaucoup trop ` a la
r eutilisation.
Les instanciations de type g en erique avec

joker

(wildcards) ont et e ajout ees pour pallier


ce probl ` eme.
36
Instanciations avec joker
Elles permettent de rel acher les contraintes sur
les types param etr es pour rendre des m ethodes
plus r eutilisables.
Faire une instanciation avec joker dun type
g en erique cest donner un type avec joker
(

est le joker) comme argument de type.


37
Exemple dinstanciation avec joker
List<? extends Number> est une liste dont
largument de type est un sous-type de Number.
On ne connat pas largument de type exact
mais on sait quil est un sous-type de Number.
38
Une bonne m ethode pour afcher les
nombres dune liste
public void
printElements(List<? extends Number> liste) {
for(Number n : liste) {
System.out.println(n.intValue());
}
}
List<Double> liste = new ArrayList<Double>();
...
printElements(liste); // Compile
39
Les

types

avec joker
<?> d esigne un type inconnu.
<? extends A> d esigne un type inconnu qui est
A ou un sous-type de A.
<? super A> d esigne un type inconnu qui est A
ou un sur-type de A
A peut etre une classe, une interface, ou m eme
un param` etre de type formel.
On dit que A contraint le joker (impose une
contrainte sur le type inconnu)
40
Remarque
Un seul type ` a la suite de extends ou de super.
41
O` u peuvent apparatre les

types

avec joker ?
Attention, cest un abus de langage, ce ne sont
pas des vrais types.
Ils ne peuvent etre utilis es que pour instancier
un type param etr e : List<? extends Number>.
Ils ne peuvent pas etre utilis es, par exemple,
pour d eclarer une variable. Ceci ne marche
pas : <? extends Number> n.
42
O` u peuvent apparatre les
instanciations de type avec joker ? (2)
Dans une classe quelconque (non g en erique ou
g en erique).
Peuvent etre utilis ees pour typer des variables,
des param` etres, des tableaux ou les valeurs
retour des m ethodes :
List<? extends Number> l;
43
Ce qui est interdit avec les
instanciations de type avec joker
Ne peuvent pas etre utilis ees pour cr eer des
objets :
new ArrayList<? extends Integer>() // interdit
Ne peuvent pas etre utilis es comme super type :
class C implements Comparable<? super C> // interdit
44
Ce qui est interdit avec les
instanciations de type avec joker (2)
Ne peuvent pas etre utilis ees pour indiquer le
type des el ements dun tableau au moment de
sa cr eation :
new List<? extends Number>[10] // interdit
Cependant le type dun tableau peut etre une
instanciation avec joker non contraint :
new List<?>[10] // autorise
45
Exemples avec les tableaux
List<? extends Number>[] t1; // autorise
t1 = new List<? extends Number>[10]; // interdit
// On cr ee un tableau dont chaque element est
// une liste dun certain type.
// Les types de chaque ligne ne sont pas oblig es
// d^ etre les m^ emes
List<?>[] t2 = new List<?>[10];
t2[0] = new ArrayList<Integer>();
t2[1] = new ArrayList<String>();
46
Quels types pour contraindre un
joker ?
Tous les types sont permis, sauf les types
primitifs, y compris les param` etres formels de
type et les instanciations avec joker
Exemples :
List<? extends String[]>
List<? extends Comparable<String>>
List<? extends Comparable<? super Long>>
List<? extends Map.Entry<?,?>>
List<? extends T> // (dans une classe g en erique
// param etree par T)
47
Exemples dutilisation
Classe ArrayList<E> :
public boolean addAll(Collection<? extends E> c)
Intuition : si une collection contient des E, on
peut lui ajouter des el ements dune sous-classe
de E.
Classe Collections :
public static boolean disjoint(
Collection<?> c1, Collection<?> c2)
Intuition : on peut toujours voir si 2 collections
ont des el ements en commun, quels que soient
les types quelles contiennent.
48
Exemple de code de la classe
Collections
static <T> void fill(List<? super T> liste, T elem) {
int size = liste.size();
for (int i = 0; i < size; i++)
liste.set(i, elem);
}
Remplace tous les el ements dune liste par un
certain el ement.
Intuition : pour remplir avec un objet de type T,
le type des el ements de la liste doit etre un
sur-type de T.
49
Exercices
1.

Ecrivez une classe MaPair qui contiendra deux
el ements dun m eme type g en erique. Noubliez
pas le constructeur ni les accesseurs et
modicateurs.
2. Changez la classe MaPair de lexercice
auparavant de facon ` a quelle puisse contenir
deux el ements des types diff erents.
50

Vous aimerez peut-être aussi