Master 2 CCI 2012-2013
POO, langage Java
Henri Garreta 

3. Application : gestion d’un club sportif

        1. Les sports possibles
        2. Les membres (version 1)
        3. Le club (version 1)
        4. Une application (simple) pour tester tout cela
        5. Le club, version 2, avec un vector pour mémoriser les membres
        6. Les membres, version 2, avec un set pour mémoriser les sports
Le signe © renvoie à la correction

Avertissement. L’exercice proposé ici doit être réalisé en suivant les indications données, et notamment en utilisant uniquement les éléments du langage java étudiés jusqu’à présent. Par conséquent, la solution obtenue sera correcte mais non optimale. Nous verrons plus tard des manières plus simples et/ou plus efficaces de résoudre le problème donné ici (lequel, d’ailleurs, relève plus de l’utilisation des SGBD que de la programmation en java).

L’objet de l’exercice est l’écriture d’une application pour gérer les membres d’un club sportif. Celui-ci se présente comme une collection d’individus, ses membres, chacun pratiquant un certain nombre de sports pris dans un ensemble donné a priori (par exemple : Tennis, Natation, Athlétisme, Volley, Rugby, Basket et Randonnée).

Pour commencer, créez un paquetage nommé version1 pour y placer les classes que vous allez écrire.

3.1. Les sports possibles ©

Les sports seront représentés par des valeurs entières conventionnelles (0 pour Tennis, 1 pour Natation, etc.), auxquelles on donnera des noms significatifs au moyen de déclarations de constantes de classe (des variables static et final), dans le genre « public static final int TENNIS = 0; »

Écrivez une classe Sports entièrement faite des déclarations de telles constantes.

En vue d’affichages ultérieurs, mettez-y aussi la définition d’une fonction « String nom(int sport) » qui reçoit le code d’un sport et renvoie le nom de ce sport (nom(TENNIS) renvoie "Tennis", nom(NATATION)renvoie "Natation", etc.)

Quel trait bizarre présente la classe Sports ? Trouveriez-vous utile que cette classe ait des instances ?

3.2. Les membres, version 1 ©

Écrivez une classe Individu, dont chaque instance représentera un membre du club. Elle se compose des membres suivants :

Le tableau sportsPratiques doit être privé, car le fait que les sports pratiqués soient représentés par un tableau de booléens est une caractéristique de l’implémentation (on verra qu’on peut faire autrement). Le déclarer privé garantit qu’aucune autre partie de l’application ne s’appuie sur ce détail, ce qui permet de le changer si par la suite on a une meilleure idée.

3.3. Le club, version 1 ©

Écrivez une classe Club dont chaque instance représente un club sportif. Elle est constituée essentiellement par la liste de ses membres, représentée pour commencer par un tableau d’objets Membre. Elle comportera donc les membres suivants :

Lors de l’ajout d’un membre, la capacité du tableau membres peut se révéler insuffisante. Il faudra détecter cela et, si nécessaire, augmenter la valeur de maxMembres (par exemple de 10 unités) et allouer un nouveau tableau, ayant cette nouvelle capacité, dans lequel il faudra recopier les éléments du précédent tableau.

Question. Quel intérêt y a-t-il à programmer un club sportif comme une « vraie » classe, avec des membres d’instance, plutôt que comme une classe entièrement faite de variables et méthodes statiques ?

3.4. Une application (simple) pour tester tout cela ©

Pour tester les classes précédentes écrivez une classe exécutable Application réduite à sa méthode main qui :

3.5. Le club, version 2, avec un vector pour mémoriser les membres ©

Pour cette question, commencez par faire une copie nommée version2, du paquetage version1 (dans eclipse il suffit de sélectionner version1 dans le panneau Package Explorer et de faire copier-coller en changeant le nom proposé).

Entre autres, cette question montre l’intérêt du principe d’encapsulation : nous allons modifier la classe Club tout en faisant attention à conserver la signature et la définition de ses méthodes publiques. Nous constaterons que l’application se compile et s’exécute parfaitement, sans qu’il faille changer quoi que ce soit dans les autres classes.

Écrivez une nouvelle version de Club en employant une autre manière de mémoriser la liste des membres : au lieu d’un tableau nous utiliserons un objet java.util.Vector (vous pouvez voir la doc ici), une structure de données ayant les deux caractéristiques suivantes :

La partie privée de la classe se réduira maintenant à  :

Si vous n’avez pas accès à la documentation en ligne de l’API, voici les méthodes de la classe Vector qui vous seront utiles (dans une présentation adaptée à nos connaissances actuelles)  :

N.B. 1. D’après sa déclaration, la méthode get renvoie un objet. Or, nous savons que les éléments du vector membres sont des individus. Nous devrons donc souvent employer cette méthode associée à un changement de type : « (Individu) membres.get(i) ».

N.B. 2. Pour écrire la méthode trouverMembre vous utiliserez indexOf et vous constaterez que cela ne fonctionne pas. C’est que nous avons fait une erreur dans la classe Individu : la signature de equals ne doit pas être celle de la question 3.2, mais plutôt « public void equals(Object unObjet) ». Corrigez equals, dans la classe Individu, constatez que cela fonctionne et expliquez ce qui se passe.

3.6. Les membres, version 2, avec un set pour mémoriser les sports ©

Commencez par faire une copie du paquetage version2 nommée version3.

Il s’agit ici de changer la classe Individu, afin de mettre en oeuvre une autre manière de représenter l’ensemble des sports pratiqués. Au lieu d’un tableau de booléens nous emploierons une structure de données TreeSet (une implémentation de la notion d’ensemble). La modestie de notre programme de test ne permettra pas d’illustrer l’intérêt de cette représentation, qui serait plus apparent si davantage d’opérations ensemblistes (réunions, intersections, etc.) étaient requises.

Écrivez une nouvelle classe Individu, dont les méthodes publiques auront les mêmes signatures (et la même signification) que celles de la première version, et dont la partie privée sera :

Encore deux remarques techniques importantes (mais prématurées par rapport à notre niveau en java ; elles seront copieusement expliquées dans la suite du cours) :

1. La classe TreeSet (comme la classe HashSet) représente une implémentation possible de la notion d’ensemble. Dans la documentation de l’API vous trouverez aussi Tree, qui représente la notion abstraite d’ensemble mais qui – puisqu’elle est abstraite  – ne peut pas avoir d’instance.

2. Les collections de la bibliothèque ont été programmées en toute généralité. Leurs éléments sont donc déclarés sous le type le plus général, Object (voyez les méthodes add et get expliquées plus haut pour les Vector). Ce qui fait que pour ajouter un entier unSport à l’ensemble des sports pratiqués nous devrons écrire « sportsPratiques.add(new Integer(unSport)) »

Inversement, si on voulait extraire un entier unSport de l'ensemble des sports pratiqués (mais on n'en a pas besoin dans l'exercice proposé) il faudrait écrire quelque chose comme « unSport = ((Integer) sportsPratiques.first()).intValue() »

Dans la suite du cours de java nous rencontrerons d’importantes simplifications de ce type de conversions. Mais vous les apprécierez davantage si vous comprenez dès maintenant ces contraintes qui pèsent sur les membres des collections.