[UMLV]

Interfaces, classes internes et itérateurs

Exercice 1 - Interface et Implémentation

Définir une interface Stack déclarant les trois méthodes classiques d'une pile : void push(Object o), Object pop() et isEmpty().

Définir une classe TableStack qui implémente l'interface Stack en utilisant un tableau.

Définir une classe ListStack qui implémente l'interface Stack en utilisant une ArrayList.

Exercice 2 - Classe abstraite

Toujours dans le domaine des piles, on désire disposer d'une méthode qui permet d'empiler (le contenu d') une pile sur une autre. Par exemple, si p1 est du type StackableStack et s'est vu empiler successivement a, b et c et que p2, du type Stack, s'est vu empiler successivement d, e et f, alors on souhaite que l'appel à p1.push(p2) aboutisse à ce qu'on puisse dépiler successivement f, e, d, c, b et a de p1.

Proposer une architecture de classes, classes abstraites et/ou interfaces permettant d'offrir cette fonctionnalité.

Exercice 3 - Table dynamique générique

Le but de cet exercice est d'écrire une classe permettant d'ajouter des élements dans une table et de parcourir celle-ci.

  1. Écrire la classe Table en stockant ses éléments dans un tableau. Pour cela, écrire un constructeur prenant en argument un entier correspondant à la taille maximale de la table, une méthode add() permettant d'ajouter un élement dans la table et une méthode size() retournant le nombre d'éléments contenus dans la table.
  2. Écrire une méthode iterator() renvoyant un objet d'une classe implantant l'interface java.util.Iterator permettant d'obtenir les élements un par un. Dans un premier temps, la classe implantant l'interface Iterator sera déclarée dans un autre fichier.
    Rappel : Cette interface est composée de trois méthodes :
    1. hasNext() qui renvoie true s'il reste encore des éléments à parcourir.
    2. next() qui renvoie l'élément parcouru et avance sur l'élément suivant. S'il n'y a plus d'élément à parcourir, la classe devra lever l'exception NoSuchElementException.
    3. remove() qui supprime de la table l'élément que next() vient de renvoyer. Ici, nous n'implémenterons pas cette méthode, mais lèverons plutôt l'exception UnsupportedOperationException.

    On prendra soin d'implanter des itérateurs dits « fail-fast» . Cela signifie que, plutôt que de prendre le risque d'aboutir à des résultats non déterministes, on préfère lever une exception (ConcurrentModificationException) dès qu'on accède à un itérateur dont la table sous-jacente a été modifiée depuis la création de cet itérateur.

  3. Faire implanter à la classe Table l'interface Iterable, afin de pouvoir utiliser ses instances avec la syntaxe des boucles « for-each» .
  4. Transformer la classe implantant l'interface Iterator en classe interne de la classe Table.
  5. Transformer cette classe en classe interne de la méthode iterator() de Table.
  6. Enfin, transformer cette classe en classe anonyme.

Exercice 4 - Réutilisation

Le but de cet exercice est d'écrire une classe permettant de stocker des voitures (cf. feuille de TD 1) dans une table de voitures en réutilisant la classe développée dans l'exercice précédent. La classe TableVoiture devra posséder les méthodes suivantes :

  1. Proposer une architecture pour implanter la classe TableVoiture en réutilisant la classe Table (Note: pas de copier/coller ni de modification de la classe Table) ;
  2. Implanter l'architecture proposée.