Travaux Pratiques n°2
Table des matières
Objectifs (1h30)
- Savoir implanter la notion d'héritage en Java
- Savoir implanter la notion de délégation en Java
- Savoir définir et utiliser des constantes, attributs et méthodes de classe
Rendu du travail
Le TP doit être rendu en fin séance, quel que soit son état d'avancement. Envoyez le source des classes (.java) ainsi que les classes compilées (.class) dans une archive zip (voir les instructions du TP1b et veiller à bien ajouter les sources !) à Gauthier Picard à la fin, avec comme sujet [LCPOO] TP5 <nom1> <nom2>. L'absence d'envoi sera sanctionnée dans la note finale.
Si vous n'avez pas terminé le TP, finissez-le avant le prochain et/ou regardez la solution dès qu'elle sera disponible.
Utilisation de l'héritage
L'héritage dans Java
En TD, nous avons vu les concepts généraux de l'héritage en programmation orientée objet, nous allons maintenant les implémenter en Java.
En Java, le mot-clé extends
permet de
signifier qu'une classe est une sous-classe d'une autre, par
exemple :
public class CompteEpargne extends Compte { ... }
En Java, l'héritage multiple n'est pas autorisé : on ne peut
avoir au maximum qu'un seul nom de classe après le mot-clé extends
.
C'est une erreur de compilation qui est indiquée par Eclipse. Pour redéfinir
une méthode f
de la super-classe dans la sous-classe, il
suffit d'écrire une méthode f
ayant la même signature que
la méthode f
de la super-classe. Ceci aura pour effet de
modifier le comportement de la méthode f
pour la
sous-classe. Pour appeler la méthode f
de la super-classe
dans une sous-classe, il faut faire appel à super.f()
.
Exercice 1
Ecrivez une classe SortedListOfStrings
représentant une liste triée d'objets du type String
. Le
tri est effectué à chaque ajout d'élément dans la liste (méthode add
).
Cette classe pourra spécialiser (hériter de) la classe ArrayList<String>
1 par exemple. Pour
comparer deux chaînes entre elles, utilisez la méthode compareTo()
de la classe String
.
Exercice 2
Ecrivez une classe SortedListOfStringsTest
contenant une méthode main
pour tester votre liste.
Le polymorphisme
Comme vu en TD, le polymorphisme consiste à pouvoir
utiliser une sous-classe B
d'une classe A
en
lieu et place de la classe A
. Toute sous-classe de ArrayList
,
donc la classe SortedListOfStrings
, peut-être utilisée au
lieu de ArrayList
.
Exercice 3
Définissez une méthode void
displayList(ArrayList<String> list)
dans la classe SortedListOfStringsTest
afin d'afficher une liste d'éléments ligne par ligne au lieu de
l'afficher sous forme de liste entre "[
" et "]
".
Exercice 4
Utilisez cette méthode pour tester votre liste.
La délégation
Limites de l'héritage
L'héritage est un outil puissant permettant de factoriser les
parties de code redondantes, par exemple. Il permet également de
développer des programmes génériques, grâce à la notion de
polymorphisme. Cependant, quelques limites existent, notamment, le fait
qu'une sous-classe hérite de toutes les méthodes de sa super-classe. Ce
qui peut entraîner des problèmes d'intégrité des données.
Prenons l'exemple de la classe SortedListOfStrings
.
Est-elle intègre ? Peut-on assurer qu'elle est toujours triée ?
Non !
En effet, on peut utiliser la méthode set(int index,
String element)
si elle hérite de la classe ArrayList
pour
remplacer un élément par un autre, non respectueux de l'ordre de tri ; à
moins que l'on redéfinisse toutes les méthodes d'accès à la liste… Ceci
impose donc de réécrire une quantité de code importante pour assurer
l'intégrité de la classe.
Une solution à ce problème récurrent est l'usage de la délégation : au lieu d'hériter d'une classe A
, une classe B
va encapsuler un objet de la classe A
et fournir les accès
nécessaires et suffisant pour l'intégrité des données. Par exemple, au
lieu d'hériter de la classe ArrayList
, la classe SortedListOfString
va posséder un attribut privé instance de la classe ArrayList
et fournir uniquement les accès utiles (création, ajout d'élément,
etc.). Elle possèdera bien les mêmes comportements, mais par contre ne
pourra pas être utiliser comme une ArrayList
(pas de
polymorphisme, donc) puisque ce n'est pas une sous-classe.
Exercice 5
Créez une nouvelle classe SortedListOfStringsUsingDelegation
représentant une liste ordonnée de String
mais par
délégation au lieu d'héritage. Les opérations fournies sont la création,
l'ajout, la taille, l'obtention d'un élément à une position donnée, la
suppression du premier élément et la conversion en chaîne de caractères.
Constantes, attributs et méthodes de classe
Le mot-clé static
Le mot-clé static
permet de définir entre
autre un attribut ou une méthode comme étant indépendant de toute
instance. Ceci signifie que de tels attributs ou méthodes peuvent être
appelés sans adresser une instance de la classe en particulier (voir les
exemples du cours et du TD).
Le mot-clé final
Le mot-clé final
permet de définir un
attribut ou une classe comme étant non modifiable. Un attribut final
représente une constante de la classe : par exemple la constante Math.PI
qui est également statique (puisque appelée. Une classe peut également
être finale, ce qui signifie qu'on ne pourra en définir de sous-classe.
Exercice 6
Modifiez la classe SortedListOfStrings
pour mesurer le nombre total d'éléments contenus dans toutes les
instances de cette classe. Créez une méthode dans SortedListOfStringsTest
pour tester votre programme.
Exercice 7
Comment définir une classe de chaînes de caractères représentant des entiers avec laquelle les entiers sont comparés en fonction de leur valeur et non de leur représentation en chaîne de caractères ? Par exemple, avec une chaîne de caractères classique, "9" > "1000". Or ici, nous voulons "9" < "1000". Proposez une solution.
Notes de bas de page:
Pour rappel, la classe ArrayList
est une classe paramétrique prenant une autre classe en paramètre, qui représente le type des objets contenu dans cette liste. Ceci explique la notation ArrayList<E>
où E
représente n'importe quelle classe, par exemple la classe String
: ArrayList<String>
.