Salut,
![Citation](https://forum.developpez.be/images/misc/quote_icon.png)
Envoyé par
hibou107
Si je défini un objet par une interface, j'ai seulement le droit d'utiliser les méthodes de l'interface et pas dans les classes d'implémentation?
Tout à fait !
![Citation](https://forum.developpez.be/images/misc/quote_icon.png)
Envoyé par
hibou107
Par exemple, dans mon exemple, s'il existe une méthode dans Arraylist et n'a pas été définie dans List, peux je l'utiliser?
Il te faudra alors recaster en ArrayList... mais en règle général avec les collections tu n'en auras pas vraiment besoin dans la plupart des cas.
Si tu as réellement besoin d'utiliser une méthode spécifique, cela signifie que tu as fait trop d'abstraction de l'implémentation !!!
Après cela dépend du choix de l'interface que tu vas utiliser.
Plus tu restes proche de l'implémentation et plus tu auras des possibilités (avec List tu as accès à la quasi-totalité des méthode d'ArrayList, sauf trimToSize() si je ne me trompe pas).
Plus tu t'en éloignes et moins tu auras de possibilités, mais ton code sera encore plus générique.
Par exemple avec cette méthode qui se contente d'afficher tous les éléments d'une ArrayList :
1 2 3 4 5
| public void printAll(ArrayList<Object> list) {
for (Object o : list) {
System.out.println(o);
}
} |
La méthode est artificiellement limitée aux ArrayList<Object>, alors qu'on pourrait utiliser l'interface List :
1 2 3 4 5
| public void printAll(List<Object> list) {
for (Object o : list) {
System.out.println(o);
}
} |
On n'a fait que charger le type déclaré du paramètre, mais notre méthode est désormais un peu plus générique puisqu'elle peut être utilisée avec n'importe quelle liste (ArrayList, LinkedList, Vector, ...)
1 2 3 4 5
| public void printAll(Collection<Object> coll) {
for (Object o : coll) {
System.out.println(o);
}
} |
Mieux : on n'a pas forcément besoin de la notion de liste ici. La notion de collection pourrait être amplement suffisante. Notre méthode acceptent désormais un plus grand nombre de type, comme les Set ou les Queue... le tout sans changer son code !
1 2 3 4 5
| public void printAll(Iterable<Object> elements) {
for (Object o : elements) {
System.out.println(o);
}
} |
On peut même se contenter de l'interface Iterable, qui indique seulement que l'on peut parcourir un ensemble d'élément. Désormais on peut l'utiliser avec encore plus de type, qui ne sont pas forcément des Collections...
En changeant uniquement le type déclaré du paramètre, on a modifié notre méthode original qui n'acceptait que très peu de type (ArrayList<Object> ou classe fille), à une méthode acceptant un très grand nombre de type différent (tout ceux qui implémentent Iterable<Object>), le tout sans changer une ligne de code.
Ceci permet une plus grande souplesse. Dans ce cas précis on se contrefiche de savoir qu'on manipule une ArrayList, un HashSet, une Queue ou n'importe quelles autres implémentations. On a uniquement besoin de parcourir les éléments contenus.
Cela permet aux utilisateurs de ta méthode de l'utiliser quelque soit l'implémentation exact qu'ils utilisent...
a++
PS : C'est un peu hors-sujet, mais pour les mêmes raisons on pourrait aller encore plus loin avec les Generics et les wildcards, car l'abstraction y est différente :
1 2 3 4 5
| public void printAll(Iterable<? extends Object> elements) {
for (Object o : elements) {
System.out.println(o);
}
} |
Désormais on n'est plus limité aux Iterable<Object> mais à n'importe quels Iterable<>
Partager