:: Enseignements :: ESIPE :: E4INFO :: 2014-2015 :: Java Avancé ::
[LOGO]

TP noté de Java Avance


Le TP consiste à implanter une interface de vue View qui permet de voir des objets sans les stocker ni pouvoir les modifier. Par contre, les modifications externes devront être automatiquement visible à travers la vue.
Rappel, vous devez configurer le workspace d'eclipse (File > Switch WorkSpace) pour qu'il corresponde au répertoire EXAM que vous avez dans le home de votre session de TP noté.

Exercice 1 - Views

On cherche à créer une interface View qui represente une vue permettant de voir de plusieurs valeurs. Une vue est un objet qui ne stoque pas lui-même les valeurs mais est capable d'accéder à celle-ci (la façon d'accéder aux valeurs sera différentes pour chaque implantation de l'interface View).
L'interface View est paramétré par le type des valeurs de la vue et possède deux méthodes
  • Une méthode size qui renvoie le nombre de valeurs de la vue.
  • Une méthode iterator qui renvoie un itérateur qui permet de parcourir les valeurs.

Nous allons chercher à écrire deux implantations de l'interface View, une dont les valeurs seront stockés dans une java.util.List et une autre dont les valeurs seront stokés dans un tableau d'entiers.
Dans un but de simplification de la correction, et aussi pour vous embétez un peu, toutes les classes ou interfaces que vous allez définir devront être définie dans le fichier Views.java en tant que classes internes ou interfaces internes de la classe fr.umlv.view.Views. Cette classe ne devra contenir en plus que des méthodes statiques.
Les tests JUnit pour toutes les questions du TP sont dans la classe ViewsTest.java.

  1. Déclarer la classe Views dans le package fr.umlv.view ainsi que l'interface interne View et ses deux méthodes size et iterator.
  2. Ecrire une classe interne ListView representant une vue dont les valeurs sont des élements d'une liste pris en paramètre à la construction.
    Ecrire de plus une méthode statique dans la classe Views nommée listAsView de telle sorte à ce que le code suivant fonctionne
           ArrayList<String> list = new ArrayList<>();
           list.add("foo");
           list.add("bar");
           View<String> view = Views.listAsView(list);
           System.out.println(view.size());  // 2
           System.out.println(view.iterator().next());  // foo
           list.set(0, "baz");
           System.out.println(view.iterator().next());  // baz
          

    La classe ListView ne devra pas être visible de l'extérieur pour forcer l'utilisateur à passer par la méthode listAsView.
  3. Si le test listOfIntegerAsObjectView ne passe pas, posez vous la question de comment dire au gentil compilateur que listAsView peut accepter des listes de sous-types (listes de types plus précis).
  4. Ecrire une seconde méthode statique intsAsView qui permet de voir une tableau d'entiers comme une View. On vous demande ici d'utiliser la syntaxe des classes anonymes pour implanter la méthode intsAsView tel que le code suivant fonctionne
           int[] array = new int[] { 2, 3, 4 };
           View<Integer> view2 = Views.intsAsView(array);
           System.out.println(view2.size());  // 3
           System.out.println(view2.iterator().next());  // 2
           array[0] = 11;
           System.out.println(view2.iterator().next());  // 11
          

    Vous ferez aussi en sorte que l'on puisse appeler intsAsView en passant directement les entiers séparés par des virgules en argument.
  5. On souhaite maintenant pouvoir effectuer une boucle dite foreach sur une View
           for(String s: view) {
             System.out.println(s);
           }
          
    Faite les changements qui s'impose dans le code.
  6. On souhaite ajouter une méthode contains à l'interface View qui renvoie vrai si l'objet passé en paramètre est accessible dans la vue.
    Comme il est possible de stocker null dans une liste en Java, on souhaite qu'il soit possible de tester si null est contenue dans une vue.
    Ecrire le code correspondant.
  7. On souhaite ajouter à l'interface View une méthode count qui prend en paramètre une lambda (celle-ci prend un paramètre et renvoie un booléen) et compte le nombre d'objet pour lequels la lambda renvoie vrai.
    Par exemple, le code suivant devra fonctionner:
           List<String> list = Arrays.asList("foo", "go", "tag", "low", "fat", "bat");
           View<String> view = Views.listAsView(list);
           System.out.println(view.count(x -> x.length() == 2)); // 1
         

    Ecrire le code correspondant.
  8. On souhaite ajouter une méthode concat à l'interface View. concat permet de concaténer (mettre l'une derrière l'autre) deux vues pour en créer une nouvelle.
    Ecrire le code correspondant.
  9. Question subsidiaire:
    En fait la méthode Views.listAsView() ne nécessite pas spécialement une liste et pourrais marcher avec n'importe quelle collection Java.
    Dans ce cas, les méthodes contains pourrait être optimisé pour avoir une complexité en O(1) si la collection sous jacente a elle-même une méthode contains dont l'implantation à une complexité en O(1).
    Modifier la signature de Views.listAsView()pour prendre n'importe quelle collection Java et modifier les méthodes contains des vues (seulement celles qui doivent être ré-implanté) en fournissant un code plus efficace pour celles-ci.