Programmation pour le TAL : classe Object, ArrayList et itérateurs

  1. Présentation : classe Object, API et listes
  2. La classe Object
    Lire le début de la section 7 (la super-classe Object) du chapitre 8 (l'héritage) du livre "Programmer en Java" jusqu'à la section 7.2.1 incluse.
    Le titre du transparent 2 est une référence à la section 2 du livre Thinking in Java de Bruce Eckel.

    Il existe en Java une classe nommée Object dont dérive toute classe que vous créez si vous ne déclarez pas cette classe comme dérivant d'une autre classe mère via le mot clé extends.
    Consultez la documentation de la classe Object de l'API : cherchez la class Object (sans italique) dans l'onglet en bas à gauche. Cette classe fournit peu de méthodes (e.g. la méthode toString(), cf. la correction des exercices géométriques, question 3), mais elle permet notamment de créer des structures de données (e.g. des listes) qui contiennent des objets de types hétéroclites, cf. plus bas les ArrayList.

  3. Les listes/tableaux dynamiques
    Lire la section 3 (les vecteurs dynamiques - classe ArrayList) du chapitre 22 (les collections et les algorithmes), à l'exclusion de la section 3.6.

    Les classes ArrayList, Iterator, etc. se trouvent dans la paquet java.util
    Pour les utiliser, pensez à ajouter "import java.util.Classe;" dans votre code, e.g. :
        import java.util.ArrayList;
        import java.util.Iterator;
    ou, pour importer toutes les classes du paquet :
        import java.util.*;
    On avait vu jusqu'ici les tableaux à indices (e.g. le tableau de type Token[] de la classe Sentence). Ces tableaux sont statiques, i.e. ils ont une taille fixe : lors de la création d'un tel tableau, la taille (le nombre d'éléments que le tableau peut recevoir) doit être indiquée à l'avance. Or, on ne connaît pas toujours cette donnée a priori. Les ArrayList sont des tableaux dynamiques auxquels ont peut ajouter et supprimer des éléments au fur et à mesure des besoins.
    On peut déclarer des listes d'un type donné, e.g. des listes de dépendances syntaxiques :
        // ici, déclaration et construction préalable de diverses instances de Token (verbToken, nounToken, etc.)
    
        ArrayList<SyntacticDepency> listeDeps = new ArrayList<SyntacticDepency>();
        SyntacticDepency syntDep = new SyntacticDepency();
        syntDep.setGovernor(verbToken);
        syntDep.setDependent(nounToken);
        syntDep.setDepLabel("obj");
        listeDeps.add (syntDep);
    
        // à noter : syntDep est déclarée comme une SyntacticDepency
        // on peut lui affecter une instance d'une classe dérivée (en l'occurrence, IndirectDependency)
        syntDep = new IndirectDepency();
        syntDep.setGovernor(noun1Token);
        syntDep.setDependent(noun2Token);
        syntDep.setDepLabel("prep");
    	  
        // syntDep est déclarée de type SyntacticDependency : 
        // on ne peut donc pas écrire syntDep.setPivot(prepToken);
        // En effet, getPivot() n'est pas une méthode de SyntacticDependency.
        // Pour pouvoir invoquer une méthode propre à IndirectDependency (ici : getPivot)
        // il faut "rappeler" explicitement que syntDep rérérence une instance de cette classe
        // par un cast (transtypage)	      
        ((IndirectDependency) syntDep).setPivot(prepToken);
    
        listeDeps.add (syntDep);
    
        // ajout d'autres dépendances
    	
    Quand on itère sur une telle liste, on sait (mieux : Java le sait aussi) que chaque objet est une instance de la classe SyntacticDepency (ou d'une classe dérivée).
        for (int i = 0; i < listeDeps.size(); i++)
        {
            SyntacticDepency currentDep = listeDeps.get(i);
            System.out.println(currentDep.getTextRepresentation());			
        }
    	
    On peut également travailler avec des listes "non typées" (cette appelation est un abus de langage). Avant la version 1.5 de Java, on ne précisait pas le type d'éléments contenus dans la liste :
    ArrayList maListe = new ArrayList ();
    En réalité, les éléments qui seront potentiellement contenus dans cette liste sont typés, mais ils sont de type Object (ou l'une de ses classes dérivées, c'est à dire toutes les classes fournies par l'API et toutes les classes que vous allez créer). Pour une telle liste, on écrit aujourd'hui explicitement qu'elle est destinée à recevoir des instances de la classe Object :
    ArrayList<Object> maListe = new ArrayList<Object> ();
    On peut ainsi ajouter toute sorte d'objets dans une telle liste, mais attention : lorsqu'on récupère un objet contenu dans la liste, il est (pour Java) de type Object. Pour utiliser des méthodes spécifiques à un classe moins générique, c'est à vous de savoir de quelle classe est l'objet et de le transtyper (pour rassurer Java). Il existe un mot-clé pour tester si un objet est une instance d'une classe donnée : instanceof. Le test "if (obj insanceof NomClasse)" renvoie true si obj est une instance de la classe, et false sinon. Exemple :
        ArrayList<Object> maListe = new ArrayList<Object> ();
        maListe.add (new Integer (5));
        maListe.add ("deuxième élément");
        maListe.add (syntDep); // instance de SyntacticDependancy déclarée plus haut
        maListe.add (nounToken); // instance de Token déclarée plus haut
        
        for (int i = 0; i < maListe.size(); i++)
        {
            Object currentObj = maListe.get(i); // on récupère une instance de Object
            if (currentObj instanceof SyntacticDependancy)
    	    System.out.println(((SyntacticDependancy) currentObj).getTextRepresentation()); // transtypage pour pouvoir invoquer une methode de SyntacticDependancy
    	else
      	    System.out.println(currentObj.toString ());
        }
    	
  4. Les itérateurs
    Il existe plusieurs manière pour itérer sur tous les éléments d'une liste. On a vu ci-dessus la méthode qui utilise une boucle for sur les indices du tableau. Il existe d'autres manières : les itérateurs (cf. présentation PDF ci-dessus) et un équivalent de foreach (en Java : "for (Object obj : maListe)") que nous ne traiterons pas dans ce cours (je vous laisse regarder si vous voulez aller plus loin). On obtient un itérateur sur une liste en invoquant la méthode iterator() sur cette liste. On précise le type de l'itérateur, qui correspond au type de la liste. Avec les listes déclarées ci-dessus, cela donne :
        Iterator<Object> itObj = maListe.iterator ();
        Iterator<SyntacticDependancy> itSynDep = listeDeps.iterator ();
        
        while (itSynDep.hasNext ())
        {
            // itérateur de type SyntacticDependancy : next() renvoie une instance de SyntacticDependancy (ou null)
    	SyntacticDependancy currentDep = itSynDep.next ();
            System.out.println (currentDep.getTextRepresentation ());
        }
        
        while (itObj.hasNext ())
        {
            // itérateur de type Object : next() renvoie une instance de Object (ou null)
    	Object currentObj = itObj.next ();
    
            if (currentObj instanceof SyntacticDependancy)
    	    System.out.println(((SyntacticDependancy) currentObj).getTextRepresentation());
    	else
      	    System.out.println(currentObj.toString);
        }
    	
    Attention : quand on parcourt une liste avec un itérateur, on ne doit pas modifier cette liste (pas d'ajout ou de suppression à cette liste). Cela vaut aussi pour un parcours avec une boucle for.
    (Il existe des mécanismes pour faire cela, qui dépassent le cadre du cours).


Retour page U.E. ]

Mention légale ]