Aller au menu - Aller au contenu

Icône La généricité en Java

Mise à jour : 12/02/2010
Difficulté : Difficile Difficile Creative Commons BY-NC-SA
96 702 visites depuis 7 jours, dont 920 sur ce chapitre classé 4/786
Pour ce concept, ajouté au JDK depuis sa version 1.5, nous allons surtout travailler avec des exemples tout au long de ce chapitre.
Le principe de la généricité est de faire des classes qui n'acceptent qu'un certain type d'objet ou de donnée, mais de façon dynamique ! :D.

Avec ce que nous avons vu au chapitre précédent, vous avez sûrement poussé un soupir de soulagement lorsque vous avez vu que ces objets acceptent tous types de données !
Par contre, un problème de taille se pose : lorsque vous voudrez travailler avec ces données, vous allez devoir faire un cast ! Et peut-être même un cast de cast, voire même un cast de cast de cast...

C'est là que se situe le problème... Mais comme je vous le disais, depuis la version 1.5 du JDK, la généricité est là pour vous aider ! :D
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Notion de base

Bon, pour vous montrer la puissance de la généricité, nous allons tout de suite voir un exemple de classe qui ne l'utilise pas ! :o
Ne vous en faites pas... Ayez confiance en moi...

Il y a un exemple très simple, que vous pourrez retrouver aisément sur le net, car il s'agit d'un des cas les plus simples pour expliquer les bases de la généricité. Nous allons coder une classe Solo. Celle-ci va travailler avec des références de type String.
Voici le diagramme de classe :

Image utilisateur


Vous pouvez voir que le code de cette classe est très rudimentaire ! On affecte une valeur, on peut la mettre à jour et la récupérer... ^^
Maintenant, si je vous demande de me faire une classe qui permette de travailler avec n'importe quel type de données, j'ai une vague idée de ce que vous allez faire... Ce ne serait pas un truc comme ça :

Image utilisateur


J'en étais sûr... :D. Créez-la et créez-vous aussi une classe avec une méthode main !
Mais si vous voulez utiliser les données de l'objet Solo, vous allez devoir faire un cast.
Testez ce code dans votre main :

Code : Java
1
2
3
4
5
6
7
8
9
public class Test {
 
        public static void main(String[] args) {
                
                Solo val = new Solo(12);
                int nbre = val.getValeur();             
        }
 
}



Vous constatez que vous tentez vainement de mettre un objet de type Object dans un objet de type Integer. Ceci est interdit ! !
La classe Object est plus globale que la classe Integer, vous ne pouvez donc pas faire cette manipulation, sauf si vous "castez" votre objet en Integer, comme ceci :

Code : Java
1
2
3
4
5
6
7
8
9
public class Test {
 
        public static void main(String[] args) {
                
                Solo val = new Solo(12);
                int nbre = (Integer)val.getValeur();            
        }
 
}


Pour le moment, on peut dire que votre classe peut travailler avec tous les types de données, mais les choses se corsent un peu à l'utilisation... Vous serez peut-être tentés de faire une classe par type de donnée (SoloInt, SoloString).
Et c'est là que la généricité est pratique. Car avec ceci, vous allez pouvoir savoir ce que contient votre objet Solo, et vous n'aurez qu'une seule classe à développer ! :o
Voilà le diagramme de classe de cet objet :

Image utilisateur


Et voici son code :


Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class Solo<T> {
 
        /**
         * Variable d'instance
         */
        private T valeur;
        
        /**
         * Constructeur par défaut
         */
        public Solo(){
                this.valeur = null;
        }
        
        /**
         * Constructeur avec paramètre
         * Inconnu pour l'instant
         * @param val
         */
        public Solo(T val){
                this.valeur = val;
        }
        
        
        /**
         * Définit la valeur avec le paramètre
         * @param val
         */
        public void setValeur(T val){
                this.valeur = val;
        }
        
        /**
         * retourne la valeur déjà "castée" par la signature de la méthode !
         * @return
         */
        public T getValeur(){
                return this.valeur;
        }       
}

Impressionnant, n'est-ce pas ?
Dans cette classe, le T n'est pas encore défini. Vous le ferez à l'instanciation de cette classe. Par contre, une fois instancié avec un type, l'objet ne pourra travailler qu'avec le type de données que vous lui avez spécifié ! Exemple de code :

Code : Java
1
2
3
4
5
6
7
8
public class Test {
 
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                Solo<Integer> val = new Solo<Integer>(12);
                int nbre = val.getValeur();             
        }
}

Ce code fonctionne très bien, mais si vous essayez de faire ceci :
Code : Java
1
2
3
4
5
6
7
8
public class Test {
 
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                Solo<Integer> val = new Solo<Integer>("toto"); //Ici on essaie de mettre une chaîne de caractère à la place d'un entier
                int nbre = val.getValeur();             
        }
}


...ou encore ceci :
Code : Java
1
2
3
4
5
6
7
8
public class Test {
 
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                Solo<Integer> val = new Solo<Integer>(12);
                val.setValeur(12.2f);   //Ici on essaie de mettre un float à la place d'un entier        
        }
}


...vous verrez une erreur dans votre zone de saisie. Ceci vous indique que votre objet ne reçoit pas le bon type d'argument, ou que votre réceptacle n'a pas le bon type de données ! Dans tous les cas de figure, il y a conflit entre le type de données que vous avez passé à votre instance lors de sa création et le type de données que vous essayez d'utiliser avec celle-ci !
Par contre, vous devez savoir que cette classe ne fonctionne pas seulement avec des Integer. Vous pouvez utiliser tous les types que vous souhaitez !


Voici une démonstration de mes dires :
Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class Test {
 
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                Solo<Integer> val = new Solo<Integer>();
                Solo<String> valS = new Solo<String>("TOTOTOTO");
                Solo<Float> valF = new Solo<Float>(12.2f);
                Solo<Double> valD = new Solo<Double>(12.202568);                
        }
}


Vous devez avoir remarqué que je n'ai pas utilisé ici les types de données que vous utilisez pour déclarer des variables de type primitif ! Ce sont les classes de ces types primitifs !

En effet, lorsque vous déclarez une variable de type primitif, vous pouvez utiliser leurs classes de définition, mais c'est rarement utilisé car très lourd à la lecture. Par exemple :
Code : Java
1
2
3
4
5
6
7
8
9
public class Test{
 
    public static void main(String[] args){
 
        int i = new Integer(12); // est équivalent à int i = 12;
        double d = new Double(12.2586); // est équivalent à double d = 12.2586;
        //...
    }
}


Bon ! Maintenant que vous avez un bel exemple de généricité, nous allons complexifier un peu les choses !

Plus loin dans la généricité !

Vous devez savoir que la généricité peut être multiple !
Nous avons créé une classe Solo, mais rien ne vous empêche de créer une classe Duo, qui elle, prend deux paramètres génériques ! Voici la modélisation de cette classe :

Image utilisateur


Vous pouvez voir que cette classe prend deux types de références non encore définies !
Voilà le code source de cette classe :
Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public class Duo<T, S> {
 
        /**
         * Variable d'instance de type T
         */
        private T valeur1;
        /**
         * Variable d'instance de type S
         */
        private S valeur2;
        
        /**
         * Constructeur par défaut
         */
        public Duo(){
                this.valeur1 = null;
                this.valeur2 = null;
        }
        
        /**
         * Constructeur avec paramètres
         * @param val1
         * @param val2
         */
        public Duo(T val1, S val2){
                this.valeur1 = val1;
                this.valeur2 = val2;
        }
        
        /**
         * Méthodes d'initialisation des deux valeurs
         * @param val1
         * @param val2
         */
        public void setValeur(T val1, S val2){
                this.valeur1 = val1;
                this.valeur2 = val2;
        }
 
        /**
         * Retourne la valeur T
         * @return
         */
        public T getValeur1() {
                return valeur1;
        }
 
        /**
         * Définit la valeur T
         * @param valeur1
         */
        public void setValeur1(T valeur1) {
                this.valeur1 = valeur1;
        }
 
        /**
         * retourne la valeur S
         * @return
         */
        public S getValeur2() {
                return valeur2;
        }
 
        /**
         * définit la valeur S
         * @param valeur2
         */
        public void setValeur2(S valeur2) {
                this.valeur2 = valeur2;
        }
        
}


Voici un code que vous pouvez tester :
Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class Test {
 
        public static void main(String[] args) {
                
                Duo<String, Boolean> dual = new Duo<String, Boolean>("toto", true);
                System.out.println("Valeur de l'objet dual: val1 = " + dual.getValeur1() + ", val2 = " + dual.getValeur2());
                
                Duo<Double, Character> dual2 = new Duo<Double, Character>(12.25895, 'C');
                System.out.println("Valeur de l'objet dual2: val1 = " + dual2.getValeur1() + ", val2 = " + dual2.getValeur2()); 
                
        }
}

Et voici le résultat :
Image utilisateur


Vous voyez qu'il n'y a rien de bien méchant ici. Ce principe fonctionne exactement comme l'exemple précédent. La seule différence est dans le fait qu'il n'y a pas un, mais deux paramètres génériques !
Attends une minute... Lorsque je déclare une référence de type Duo<String, Boolean>, je ne peux plus la changer en un autre type !

En fait, avec ce que je vous ai fait voir, non.
Pour le moment, si vous faites :
Code : Java
1
2
3
4
5
6
7
8
9
public class Test {
 
        public static void main(String[] args) {
                
                Duo<String, Boolean> dual = new Duo<String, Boolean>("toto", true);
                System.out.println("Valeur de l'objet dual: val1 = " + dual.getValeur1() + ", val2 = " + dual.getValeur2());
                dual = new Duo<Double, Character>();
        }
}

vous violez la contrainte que vous avez émise lors de la déclaration du type de référence ! Mais il existe un moyen de contourner ça. :D
Tout simplement en disant, à la déclaration, que votre objet va accepter tous types de références ! Comment en utilisant ce qu'on appelle le wildcard : ?.
Comme ceci :
Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class Test {
 
        public static void main(String[] args) {
                
                Duo<?, ?> dual = new Duo<String, Boolean>("toto", true);
                
                System.out.println("Valeur de l'objet dual: val1 = " + dual.getValeur1() + ", val2 = " + dual.getValeur2());
                dual = new Duo<Double, Character>();
                dual = new Duo<Integer, Float>();
                dual = new Duo<Solo, Solo>();
        }
}


Avec ce type de déclaration, votre objet accepte bien n'importe quel type de référence !
Intéressant, non ?
Donc si vous suivez bien, on va pouvoir encore corser la chose ! :pirate:

Généricité et collection

Vous pouvez aussi utiliser la généricité sur les objets servant à gérer des collections.
C'est même l'un des points les plus utiles de la généricité ! ;)

En effet, lorsque vous listiez le contenu d'un ArrayList par exemple, vous n'étiez JAMAIS sûrs à 100 % de savoir sur quel type de référence vous alliez tomber... Eh bien ce calvaire est terminé et le polymorphisme va pouvoir réapparaître, plus puissant que jamais !

Voyez comment utiliser (même si vous l'aviez deviné) la généricité avec les collections :
Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.util.ArrayList;
 
 
public class Test {
 
        public static void main(String[] args) {
                
                System.out.println("Liste de String");
                System.out.println("------------------------------");
                ArrayList<String> listeString= new ArrayList<String>();
                listeString.add("Une chaîne");
                listeString.add("Une Autre");
                listeString.add("Encore une autre");
                listeString.add("Allez, une dernière");
                
                for(String str : listeString)
                        System.out.println(str);
                
                
 
                System.out.println("\nListe de float");
                System.out.println("------------------------------");
                
                ArrayList<Float> listeFloat = new ArrayList<Float>();
                listeFloat.add(12.25f);
                listeFloat.add(15.25f);
                listeFloat.add(2.25f);
                listeFloat.add(128764.25f);
                
                for(float f : listeFloat)
                        System.out.println(f);
        }
}


Voici le résultat de ce code :
Image utilisateur


La généricité sur les listes est régie par les mêmes lois vues précédemment !
Pas de type float dans un ArrayList<String>.

Vu qu'on y va crescendo, on pimente à nouveau le tout !

Héritage et généricité

Là où les choses sont pernicieuses, c'est quand vous utilisez des classes usant de la généricité avec des objets usant de la notion d'héritage !
L'héritage dans la généricité est une des choses les plus complexes à comprendre en Java. Pourquoi ? Tout simplement parce qu'elle va à l'encontre de ce que vous avez appris jusqu'à présent... o_O

Acceptons le postulat suivant


Nous avons une classe Voiture dont hérite une autre classe VoitureSansPermis, ce qui nous donnerait le diagramme suivant :

Image utilisateur


Jusque-là, c'est simplissime. :-°
Maintenant, ça se complique :
Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import java.util.ArrayList;
 
 
public class Test {
 
        public static void main(String[] args) {
                
                ArrayList<Voiture> listVoiture = new ArrayList<Voiture>();
                ArrayList<VoitureSansPermis> listVoitureSP = new ArrayList<VoitureSansPermis>();
                
                listVoiture = listVoitureSP;//Interdit ! ! ! ! 
        }
}

Je sais que même si vous aviez l'habitude de la covariance des variables, ceci n'existe pas sous cette forme avec la généricité !
Pourquoi cela ?

Imaginez deux secondes que l'instruction interdite soit permise !
Dans listVoiture, vous avez le contenu de la liste des voitures sans permis, et rien ne vous empêche d'ajouter une voiture... Là où le problème prend toute son envergure, c'est lorsque vous allez vouloir sortir toutes les voitures sans permis de votre variable listVoiture, eh oui ! Vous y avez rajouté une voiture ! :o
Lors du balayage de la liste vous aurez, à un moment, une référence de type VoitureSansPermis à qui vous tentez d'affecter une référence de type Voiture. Voilà pourquoi ceci est INTERDIT ! !

L'une des solutions consiste à utiliser le wildcard.

Je vais maintenant vous indiquer quelque chose d'important !
Avec la généricité, vous pouvez aller encore plus loin... Nous avons vu comment restreindre le contenu d'une de nos listes. Mais nous pouvons aussi élargir son contenu ! Si je veux par exemple qu'un ArrayList puisse avoir toutes les instances de Voiture et de ses classes filles. Comment faire ?

Ce qui suit s'applique aussi aux interfaces susceptibles d'être implémentées par une classe !


Attention les yeux, ça pique :
Code : Java
1
2
3
4
5
6
7
8
import java.util.ArrayList;
public class Test {
 
        public static void main(String[] args) {
                //Voici un ArrayList n'acceptant que des instances de Voiture ou de ses sous-classes
                ArrayList<? extends Voiture> listVoitureSP = new ArrayList<VoitureSansPermis>();           
        }
}

Et une application de ceci consiste à faire des méthodes génériques, comme par exemple avoir une méthode qui permette de lister toutes les valeurs de notre ArrayList citée précédemment. Voici :
Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import java.util.ArrayList;
public class Test {
 
        public static void main(String[] args) {
                
                ArrayList<? extends Voiture> listVoitureSP = new ArrayList<VoitureSansPermis>(); 
                afficher(listVoitureSP);          
        }
        
        /**
         * Méthode générique !
         * @param <T>
         * @param list
         */
        static void afficher(ArrayList<? extends Voiture> list){
                for(Voiture v : list)
                        System.out.println(v.toString());
        }
        
}


Eh ! Attends, on a voulu ajouter des objets dans notre collection et le programme ne compile plus !


Oui, alors, ce que je ne vous avait pas dis, c'est que, dès que vous utilisez le wildcard combiné avec le mot clé extends, vos listes seront verrouillées en insertion : Elles se transforment en collections en lecture seule...

Pourquoi ça ?

En fait, il faut déjà savoir que c'est à la compilation du programme que Java ne vous laisse pas faire.
Le verrou vient du fait que, vu que le wildcard signifie "tout objet" combiné avec extends signifiant "héritant", au moment de la compilation, Java n'a aucune idée de l'objet qu'on vient d'assigner à notre collection : les concepteurs ont donc préféré bloquer ce mode d'utilisation.

Par contre, ce type d'utilisation fonctionne à merveille pour la lecture :
Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.util.ArrayList;
import java.util.List;


public class Main {

	public static void main(String[] args){
		
		//Liste de voiture
		ArrayList<Voiture> listVoiture = new ArrayList<Voiture>();
		listVoiture.add(new Voiture());
		listVoiture.add(new Voiture());
		
		ArrayList<VoitureSansPermis> listVoitureSP = new ArrayList<VoitureSansPermis>();
		listVoitureSP.add(new VoitureSansPermis());
		listVoitureSP.add(new VoitureSansPermis());
		
		affiche(listVoiture);
		affiche(listVoitureSP);
	}
	
	/**
	 * Avec cette méthode, on accepte aussi bien les collections de Voiture 
	 * que les collection de VoitureSansPermis
	 * @param list
	 */
	static void affiche(List<? extends Voiture> list){

		for(Voiture v : list)
			System.out.print(v.toString());
	}
	
}


Avant que vous ne posiez la question : NON ! Déclarer la méthode comme ceci affiche(List<Voiture> list) ne vous permet pas de parcourir des listes de VoitureSansPermis, même si celle-ci hérite de la classe Voiture.
Les méthodes déclarées avec un type générique sont verrouillées afin de n'être utilisées qu'avec ce type bien précis, toujours pour les mêmes raisons que ci-dessus !

Pfiou ! C'est bien compliqué tout ça...

Attendez, ce n'est pas encore fini. Nous avons vu comment élargir le contenu de nos collections (pour la lecture), nous allons voir comment restreindre les collections acceptées par nos méthodes.
La méthode :
Code : Java
1
2
3
4
5
static void affiche(List<? extends Voiture> list){

  for(Voiture v : list)
	System.out.print(v.toString());
}

Autorise un objet de type List de n'importe quel type dont Voiture est la super classe.

L'instruction suivante signifie :
La méthode autorise un objet de type List de n'importe quel super classe de la classe Voiture, Voiture y compris.

Code : Java
1
2
3
4
5
static void affiche(List<? super Voiture> list){

  for(Object v : list)
	System.out.print(v.toString());
}


Ce code fonctionne donc parfaitement :

Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args){
		
		//Liste de voiture
		List<Voiture> listVoiture = new ArrayList<Voiture>();
		listVoiture.add(new Voiture());
		listVoiture.add(new Voiture());
		
		ArrayList<Object> listVoitureSP = new ArrayList<Object>();
		listVoitureSP.add(new Object());
		listVoitureSP.add(new Object());
		
		affiche(listVoiture);		
	}
	
	/**
	 * Avec cette méthode, on accepte aussi bien les collections de Voiture 
	 * que les collection d' Object : super classe de toutes les classes
	 * @param list
	 */
	static void affiche(List<? super Voiture> list){

		for(Object v : list)
			System.out.print(v.toString());
	}



Je conçois bien que ceci est un peu ardu à comprendre... Mais vous en aurez sûrement besoin dans une de vos prochaines applications !

Bon : je crois que nous avons fait un bon tour du sujet même si nous n'avons pas tout abordé... Allez, le topo classique. ^^

Ce qu'il faut retenir

  • La généricité est apparue depuis le JDK 1.5.
  • Ce concept est très utile pour développer des objets pouvant travailler avec plusieurs types de données.
  • Vous passerez donc moins de temps à développer des classes pour traiter de façon identique des données différentes.
  • La généricité permet de ré-utiliser le polymorphisme sans risque avec les collections.
  • Cela vous permet une meilleure robustesse du code.
  • Vous pouvez coupler les collections avec la généricité !
  • Le wildcard (?) permet de dire que n'importe quel type peut être traité et donc accepté !
  • Dès que le wildcard (?) est utilisé sur une collection, cela revient à rendre la dite collection en lecture seule !
  • Vous pouvez élargir le champ d'acceptation d'une collection générique grâce au mot clé extends.
  • L'instruction <? extends MaClasse> autorise toutes les collections de classes ayant pour super type MaClasse.
  • L'instruction <? super MaClasse> autorise toutes les collections de classes ayant pour type MaClasse et tous ses supers types !
  • Pour ce genre de cas, les méthodes génériques sont particulièrement adaptées et permettent d'utiliser le polymorphisme dans toute sa splendeur !

Q.C.M.

Qu'est-ce que la généricité ?
Quel est le symbole du wildcard ?
À quoi sert le wildcard ?
Quel mot clé peut suivre le wildcard afin de dire que les types de données passées en paramètres peuvent être des enfants d'une classe ?
Si j'ai une classe ObjectA qui implémente une interface Face, que dois-je mettre comme paramètre de généricité à une ArrayList pour que les types acceptés soient du type de mon interface ou des objets qui l'implémentent ?

Statistiques de réponses au QCM

J'espère que ce chapitre n'a été trop... lourd...
En attendant, nous avons presque terminé cette seconde partie... La programmation d'interface graphique se rapproche !
Mais il nous reste une dernière chose à aborder qui peut s'avérer importante ! La réflexivité.
Chapitre précédent Sommaire Chapitre suivant

Partager

39 commentaires pour "La généricité en Java"
Note moyenne : 3.57 / 4 (1025 votes)
Pseudo Commentaire
Hors ligne denver22 # Posté le 07/09/2011 à 16:41:46
Avatar

Bonjour Cysboy, d'abord merci pour ce tuto :)
il m'est très utile pour me former car je vais en avoir besoin pour le boulot très rapidement. Je passe donc peut être un peu vite sur certains points néanmoins j'ai un problème avec ta phrase :
Citation : cysboy
L'instruction suivante signifie :
La méthode autorise un objet de type List de n'importe quel super classe de la classe Voiture, Voiture y compris.
Code : Java
1
2
3
4
5
static void affiche(List<? super Voiture> list){

  for(Object v : list)
	System.out.print(v.toString());
}

Quand tu dis n'importe quel super classe de la classe voiture ça donne l'impression qu'il peut y en avoir plusieurs. hors il me semble que tu as insisté sur le fait qu'une classe ne peut avoir qu'une seule super classe. Peux tu me confirmer ce point?
Hors ligne kambous # Posté le 06/10/2011 à 08:02:36

Bonjour denver22,
lorsque cysboy dit "n'importe quel super classe de la classe voiture", c-a-d la hiérarchie des classes mères, jusqu'à arriver à la classe Object dont toutes les classes héritent d'elle.
Hors ligne Dorian Grey # Posté le 04/02/2012 à 13:46:38
Avatar

Avis : Décevant

Désolé mais le tuto est extremement indigeste, là on a une énumération de notions abstraites, j'ai beaucoup trop de mal a me concentrer pour les retenir du coup c'est foutu je peux m’arrêter là.

Ca me fait penser à tous ces cours sur le PHP qui nous assomment en nous énumérant des trucs dont on capte pas l'interet, et où on doit attendre le tout dernier chapitre pour en comprendre la véritable utilité.
Cest grace au SDZ et au fait que MySQL fut rapidement abordé que j'ai pu finalement apprendre le PHP.

Ca serait beaucoup mieux si ce tuto abordait toutes ces notions progressivement, que ca soit ponctué de choses plus amusantes..

Je laisse tomber
 
Hors ligne ichigo01 # Posté le 14/02/2012 à 18:30:10

Avis : Bon

Il manque un : affiche(listVoitureSP); dans l'exemple qui illustre l'utilisation de super classe ...

J'ai lu le chapitre et je me pose toujours la question : quelle est la vrai utilité de cette "généricité" ?
(je sais, le principe du "Zéro", "vous comprendrez son utilité plus tard")
Hors ligne rofa # Posté le 16/05/2012 à 18:03:59

Bonjour,

Vous dites: " Les méthodes déclarées avec un type générique sont verrouillées afin
de n'être utilisées qu'avec ce type bien précis ".
Pourquoi alors le programme suivant fonctionne ?:


import java.util.ArrayList;
public class Test {

public static void main(String[] args) {
// TODO Auto-generated method stub

ArrayList<Ville> v = new ArrayList<Ville>();

Ville v1 = new Ville("rennes", 5464, "france");
v.add(v1);

Capitale c = new Capitale("paris", 98768, "france", "hollande");
v.add(c);

afficher(v);

}
static void afficher(ArrayList<Ville> list){
for(Ville v : list)
System.out.println(v.descriToi());
}
}

Voir tous les commentaires