TD de Programmation Orientée Objet

Interfaces - Collections

dernière modification par Philippe.Genoud@imag.fr.

Philippe Genoud, Xavier Girod

Objectifs :

On souhaite réaliser une application de gestion d'un annuaire téléphonique qui permet d'associer à une personne un ou plusieurs numéros de téléphone.

Cette application s'articulera autour des classes et interfaces suivantes (cliquer ici pour voir leurs API) :

Votre travail consiste à réaliser et tester différentes implémentations des interfaces IListeNumTel et IAnnuaire en utilisant les services de différentes classes du package java.util.

ATTENTION : dans un premier temps il vous est demandé de ne travailler qu'avec l'API du JDK 1.4, donc de ne pas utiliser les fonctionnalités liées à la généricité introduites à partir de la version 1.5.

Pour accéder à la documentation du JDK 1.4.2 : http://java.sun.com/j2se/1.4.2/docs/api/index.html

Le source de ces différentes classes et interfaces vous est fourni. Téléchargez et décompressez sur votre compte le fichier annuaire.zip qui contient les fichiers suivants :

1ère partie : Première implémentantion de l'interface IListeNumTel

L'interface IListeNumTel définit une liste des numéros de téléphone pour une personne. Une liste de numéros n'est jamais vide, elle contient toujours au moins un numéro.

La spécification des méthodes publiques de l'interface IListeNumTel est donnée dans le tableau suivant. Pour plus de détails on se réfèrera à la documentation complète de IListeNumTel

Method Summary
 boolean ajouter(int index, NumTel num)
          ajoute un numéro à une position donnée dans la liste, sans effet si le numéro est déjà présent dans la liste.
 boolean ajouterDebut(NumTel num)
          ajoute un numéro au début de la liste, sans effet si le numéro est déjà présent dans la liste.
 boolean ajouterFin(NumTel num)
          ajoute un numéro à la fin de la liste, sans effet si le numéro est déjà présent dans la liste.
 boolean contientNumero(int num)
          Teste la présence d'un numéro dans la liste.
 java.util.Iterator iterator()
          Renvoie un itérateur sur les numéros de téléphone contenus dans la liste.
 int nbNumeros()
          retourne le nombre de numéros de la liste (>=1).
 NumTel numero(int index)
          retourne le ième numéro de la liste, null si la liste contient moins de i numéros.
 NumTel premierNumero()
          retourne le premier numéro de la liste (il existe forcément)
 boolean retirer(int num)
          Enlève un numéro de la liste, cette opération n'est possible que si la liste contient au moins deux numéros (nbNumero()>1).
 java.lang.String toString()
          Retourne dans une chaîne de caractères la séquence des numéros contenu dans cette liste.

Votre premier travail consiste à réaliser et tester une implémentation de cette interface. Pour réaliser cette implémentation vous vous appuyerez sur les services de java.util.List pour stocker les différents numéros de téléphone.

  1. A votre avis pourquoi la classe ListeNumtel délègue-t-elle la gestion de la liste des numéro de téléphone à un objet java.util.List plutôt que d'hériter d'une implémentation de java.util.List (par exemple java.util.ArrayList) ?
  2. Ecrire et compiler votre classe ListeNumTel implémentation de l'interface IListeNumtel
  3. Tester votre implémentation de l'interface ListeNumtel avec le programme ListeNumTelTest. Pour cela vous remplacerer dans la code de ListeNumTelTest les références à ImpListeNumtel par des références à votre classe ListeNumTel.

2ème partie : Réalisation de la classe Annuaire

Un annuaire permet d'associer à une personne une liste de numéros de téléphone. Les méthodes de l'interface IAnnuaire sont les suivantes (pour plus de détails on se réfèrera à la documentation complète de IAnnuaire

Method Summary
 void afficher()
          affiche l'intégralité de l'annuaire, sous la forme d'une personne par ligne suivie de ses numéros de téléphone.
 boolean ajouterEntree(Personne p, IListeNumTel nums)
          ajoute une nouvelle entrée dans l'annuaire.
 void ajouterNumeroDebut(Personne p, NumTel n)
          ajoute un numero au début de la liste des numéros d'une personne.
 void ajouterNumeroFin(Personne p, NumTel n)
          ajoute un numero à la fin de la liste des numéros d'une personne.
 ListeNumTel numeros(Personne p)
          retourne les numéros si la personne est absente retourne null
 java.util.Iterator personnes()
          renvoie un iterateur sur l'ensemble des personnes contenues dans l'annuaire
 NumTel premierNumero(Personne p)
          retourne le premier numéro d'une personne, si la personne n'est pas dans l'annuaire retourne null.
 void supprimer(Personne p)
          supprime une personne de l'annuaire.
 void supprimer(Personne p, int n)
          supprime un numero donné pour une personne.
 java.lang.String toString()
          retourne une chaîne représentant l'intégralité de l'annuaire.

Exercice 1 :

a) Réaliser une classe Annuaire implémentant l'interface IAnnuaire.

On utilisera comme structure de données pour l'annuaire une table associative (interface  Map) : la personne jouant le rôle de clé et la liste des numéros de téléphone étant la valeur associée à cette clé (on prendra une HashMap comme implémentation). Dans un premier temps on se contentera d'écrire une implémentation complète uniquement pour les méthodes ajouterEntree(Personne, ListeNumTel),personnes(), afficher() et numeros() de la classe Annuaire.

b) Tester ces méthodes avec le petit programme principal suivant qui :

  public static void main(String[] args) {

    // crée un annuaire vide
    IAnnuaire an = new Annuaire();
 
    // ajoute deux personnes à l'annuaire
    Personne p1 = new  Personne(Personne.MLLE,"DURAND","Sophie");
    an.ajouterEntree(p1,new ListeNumTel(new NumTel(151171,'D')));

    an.ajouterEntree(new Personne(Personne.MR,"DUPONT","Jean"),
                             new ListeNumTel(new NumTel(151170,'P')));

    an.ajouterEntree(new Personne(Personne.MR,"DUSCHMOL", "Louis"), 
new ListeNumTel(new NumTel(146761,'P')));

an.ajouterEntree(new Personne(Personne.MR,"AARGHH", "Robert"),
new ListeNumTel(new NumTel(140361,'P'))); // imprime l'annuaire System.out.println("------------------------------"); System.out.println(an); System.out.println("------------------------------"); // Recherche des numéros de Sophie DURAND System.out.println("numeros de " + p1); System.out.println(an.numeros(p1)); // Recherche des numéros de Jean DUPONT Personne p2 = new Personne(Personne.MR,"DUPONT","Jean"); System.out.println("numeros de " + p2); System.out.println(an.numeros(p2)); }

Constatez que la recherche du numéro pour Jean DUPONT a échoué alors qu'elle a réussi pour Sophie DURAND. Quelle explication donnez vous à cela ?

c) Modifiez la classe Personne de manière à corriger les erreurs détectées précédemment.

Exercice 2 :

On voudrait que l'itérateur fournissant les différentes personnes enregistrées dans l'annuaire permette d'obtenir celles-ci selon l'ordre alphabétique, ce qui n'est pas garanti par une HashMap. Pour cela il vaudrait mieux utiliser comme implémentation de l'annuaire un objet instance de la classe TreeMap.

  1. Dans votre implémentation de l'annuaire remplacez HashMap par TreeMap
  2. Recompilez votre application et exécutez. Quel problème cela pose-t'il ? Quelle doit être la propriété de la classe Personne ?
  3. Faites les modifications nécessaires, refaites le test précédent et constatez les modifications lors de l'affichage de l'annuaire.

Exercice 3:

Ecrivez l'implémentation complète de la classe Annuaire et un programme de test de cette classe.

Exercice 4 :

On veut ajouter la méthode suivante à l'annuaire:

   /** 
    *  donne l'ensemble de toutes les personnes de l'annuaire dont le nom 
* débute par une chaîne donnée.
* @param s1 la chaine pour la recherche
* @return l'ensemble des personnes de l'annuaire dont le nom débute
* par s1
*/
public Set entreesPourChaine(String s1)

Réaliser cette évolution et tester cette nouvelle méthode. (Indication : avant d'écrire ce code examinez attentivement toutes les méthodes de TreeMap)

3ème partie : Utiliser les nouvelles fonctionnalités de java 5

ATTENTION : vous devez pour cette troisième partie travailler avec le JDK 1.5.

Avant toute chose vérifiez que vous disposer bien d'une machine virtuelle 1.5 pour exécutez vos programme. La commande java -version doit donner :

java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)

Vous pourrez donc bien exécuter des programmes utilisant les nouvelles fontctionnalités de java 1.5. Mais, si plusieurs versions de java cohabitent sur votre poste de travail, il vous faut vérifier que le compilateur que vous utiliserez reconnait les nouveautés du langage, en d'autres termes qu'il s'agit bien d'un compilateur 1.5. Vous pouvez vérifiez cela avec la commande javac -version qui doit donner :

javac 1.5.0 <-- pour les versions antérieures il n'y a pas de numéro de version
javac: no source files
Usage: javac <options> <source files>
where possible options include:
-g Generate all debugging info
...

Pour accéder à la documentation du JDK 1.5.0 : http://java.sun.com/j2se/1.5.0/docs/api/index.html

 

Exercice 1 : Modifier les différentes classes de votre application afin d'exploiter dans vos implémentations des interfaces IListeNumTel et IAnnuaire les possibilités offertes par les collections génériques

Exercice 2 : La civilité des personnes est codée par un entier. Modifier votre application, afin d'utiliser un type enuméré pour représenter l'attribut de civilité