Travaux Pratiques n°2

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:

1

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>E représente n'importe quelle classe, par exemple la classe String : ArrayList<String>.


Gauthier Picard