Exercices dirigés NFP121


Plusieurs classes et interfaces



QUESTION 1 : Reprenez et exécutez la diapositive 15 du cours, vérifiez la trace produite.

QUESTION 2 : Ajoutez la classe des entiers positifs, et sa classe de tests unitaires

  La classe des entiers positifs, comme son nom l'indique ne peut contenir que des entiers positifs ou nuls.
  Le constructeur, le mutateur, les opérations sont concernés ainsi que la méthode de conversion d'une String en entier positif.
  Une exception EntierPositifException est levée si la valeur transmise est négative.

La classe Entier est fournie :

public class Entier {
  private int valeur;

  public Entier(int valeur){this.valeur = valeur;}
  
  public void inc(){this.valeur++;}
  public void dec(){this.valeur--;}
  
  public int getValeur(){return this.valeur;}
  public void setValeur(int valeur){this.valeur = valeur;}

  public String toString(){return Integer.toString(this.valeur);}
  
  public String toString(int base){return Integer.toString(this.valeur, base);}
  
  public boolean equals(Object obj){
    if(obj instanceof Entier){
      Entier e = (Entier) obj;
      return this.valeur == e.valeur;
    }
    return false;
  }
  
  public int hashCode(){return this.valeur;}
  public boolean repOk(){return true;}
  public Integer af(){return new Integer(getValeur());}
  
  public static Entier parseEntier(String s) throws NumberFormatException{
//     try{
      int valeur = Integer.parseInt(s);
      return new Entier(valeur);
//     }catch(NumberFormatException e){
//       throw e;
//     }
  }
}

La classe EntierPositifException est ci-dessous:

public class EntierPositifException extends RuntimeException{
 
  public EntierPositifException(){
    super();
  }

  public EntierPositifException(String msg){
    super(msg);
  }
}

La classe de tests EntierPositif ci-dessous peut être complétée :

public class EntierPositifTest extends junit.framework.TestCase{

  public void testConstructeurEntierPositif(){
    Entier e = null;
    try{
      e = new EntierPositif(-3);
      fail("une exception est attendue, appel du constructeur avec un nombre négatif");
    }catch(Throwable exc){
      assertEquals("constructeur en défaut", exc.getMessage());
    }
    try{
      e = new EntierPositif(3);
      assertEquals(3, e.getValeur());
    }catch(Throwable exc){
      fail("une exception n'est pas attendue ici");
    }
  }
  
  public void testIncEntierPositif(){
    Entier e = new EntierPositif(Integer.MAX_VALUE);
    try{
      e.inc();
      fail("une exception est attendue");
    }catch(Throwable exc){
      assertEquals("inc en défaut", exc.getMessage());
    }
    try{
      e = new EntierPositif(3);
      e.inc();
      assertEquals(4, e.getValeur());
    }catch(Throwable exc){
      fail("une exception n'est pas attendue ici");
    }
  }
  
  public void testDecEntierPositif(){
    Entier e = new EntierPositif(0);
    try{
      e.dec();
      fail("une exception est attendue");
    }catch(Throwable exc){
      assertEquals("dec en défaut", exc.getMessage());
    }
    e = new EntierPositif(3);
    try{
      e.dec();
      assertEquals(2, e.getValeur());
    }catch(Throwable exc){
      fail("une exception n'est pas attendue ici");
    }
  }
  
  public void testSetValeurEntierPositif(){
    Entier e = new EntierPositif(0);
    try{
      e.setValeur(-5);
      fail("une exception est attendue");
    }catch(Throwable exc){
      assertEquals("setValeur en défaut", exc.getMessage());
    }
    e = new EntierPositif(3);
    try{
      e.setValeur(2);
      assertEquals(2, e.getValeur());
    }catch(Throwable exc){
      fail("une exception n'est pas attendue ici");
    }
  }
}

QUESTION 3 : Ajoutez à la classe EntierPositif, l'invariant de classe repOk et la fonction d'abstraction pour la classe EntierPositif. Enrichissez la classe de tests unitaires

 

QUESTION 4 : Soit une table bornée d'entiers, entiers éventuellement positifs, dont la taille est fixée à la construction de celle-ci.

Cette table implémente java.lang.Iterable, soit la méthode Iterator<Entier> iterator()

Proposez la classe TableEntiers et ses principales opérations, les noms des méthodes sont ci-dessous (style javadoc)

Comme aide, vous trouverez ci-dessous un début d'implémentation de la table, avec l'invariant de classe et une fonction d'abstraction, ce n'est qu'une proposition... L'implémentation de l'itérateur utilise une classe interne.

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
public class TableEntiers implements Iterable<Entier>{
    private Entier[] table;
    private int taille=0;
    
    public boolean repOk(){
      if(table==null || taille <0 || taille > table.length) return false;
      for(int i=0; i<taille; i++){
        if(table[i] == null) return false;  
      }
      return true;
    }
    
    public List<Integer> af(){
      List<Integer> liste = new ArrayList<Integer>();
      for(int i=0; i<taille; i++){
        liste.add(table[i].af());
      }
      return liste;
    }
    
    /** Création d'une table d'entiers.
     * @param capacite la capacité maximale
     */
    public TableEntiers(int capacite){
       if(capacite<0) capacite=0;
       this.table = new Entier[capacite];
       this.taille = 0;
    }

  
    public void ajouter(Entier e)throws TablePleineException{
      if(e==null)throw new NullPointerException();
      if(estPleine()) throw new TablePleineException();
      table[taille] = e;
      taille++;
    }
    
 
    public void retirer(Entier e){
      // à compléter
   
    }
    
    public boolean contient(Entier e){
     
      // à compléter
      return false;
    }
    
    public int taille(){
      return this.taille;
    }
    
    public boolean estPleine(){
      return taille == table.length;
    }
    
    public boolean estVide(){
      return taille == 0;
    }
    
    public String toString(){
      String res = "[";
           // à compléter
      return res + "]";
    }
    
    public Iterator<Entier> iterator(){
      return new TableIterator();
    }
    
    private class TableIterator implements Iterator<Entier>{  
      private int index = 0;
      private boolean nextOk; // next() a été effectué au moins une fois avant remove
      public boolean hasNext(){
      // à compléter
        return false;
      }
      
      public Entier next(){
      // à compléter
        nextOk = true;
        return e;
      }
 
      public void remove(){
        if(nextOk){ // supprimer le courant, soit contenu[index-1]
          nextOk = false;
      // à compléter
      // cette méthode pourrait vous être utile, 
      // System.arraycopy ,
       
	//  un exemple ici
 
        }else
           throw new IllegalStateException(); 
      }
   }
    
}

Les classes pour les exceptions susceptibles d'être levées sont ici réduites au minimum...

public class TableException extends Exception{
}
public class TablePleineException extends TableException{
}
public class TableVideException extends TableException{
}

Votre classe doit vérifier la classe de tests ci dessous, classe de tests qu'il vous faudra compléter

import java.util.List;
import java.util.Iterator;
public class TableEntiersTest extends junit.framework.TestCase{
 
  public void testAjout(){
    try{
      TableEntiers table = new TableEntiers(4);
      assertEquals(0, table.taille());
      assertEquals(true, table.estVide());
      assertEquals(false, table.estPleine());
      
      table.ajouter(new Entier(-2));
      assertEquals(1, table.taille());
      assertEquals(false, table.estVide());
      assertEquals(false, table.estPleine());
      
      table.ajouter(new EntierPositif(1));
      assertEquals(2, table.taille());
      assertEquals(false, table.estVide());
      assertEquals(false, table.estPleine());
      
      table.ajouter(new Entier(2));
      assertEquals(3, table.taille());
      assertEquals(false, table.estVide());
      assertEquals(false, table.estPleine());
      
      table.ajouter(new EntierPositif(3));
      assertEquals(4, table.taille());
      assertEquals(false, table.estVide());
      assertEquals(true, table.estPleine());
      // ...
    }catch(TableException exc){
      fail("Une exception n'est pas attendue ici ...");
    }
  }
  
  public void testRetrait(){
    try{
      TableEntiers table = new TableEntiers(4);
      table.ajouter(new Entier(0));
      table.ajouter(new Entier(1));
      assertEquals(2, table.taille());
      table.retirer(new Entier(0));
      assertEquals(1, table.taille());
      assertFalse(table.contient(new Entier(0)));
      assertTrue(table.contient(new Entier(1)));
      table.retirer(new Entier(2));
      assertEquals(1, table.taille());
      table.retirer(new Entier(1));
      assertEquals(0, table.taille());
      table.ajouter(new Entier(0));
      table.ajouter(new Entier(1));
      table.ajouter(new Entier(0));
      table.ajouter(new Entier(2));
      assertEquals("[0, 1, 0, 2]",table.toString());
      table.retirer(new Entier(0));
      assertEquals(3, table.taille());
      assertEquals("[1, 0, 2]",table.toString());
      table.retirer(new Entier(2));
      assertEquals(2, table.taille());
      assertEquals("[1, 0]",table.toString());
      // ...
    }catch(TableException exc){
      fail("Une exception n'est pas attendue ici ...");
    }
  }
    
  public void testIterator() {
    try{
      TableEntiers table = new TableEntiers(6);
      for(int i=10;i < 16;i++){
        table.ajouter(new Entier(i));
      }
      Iterator<Entier> it = table.iterator();
      for(int i=0;i < 6; i++){
        assertEquals(new Entier(i+10), it.next());
      }
      assertFalse(it.hasNext());
      //...
    }catch(TableException exc){
      fail("Une exception n'est pas attendue ici ...");
    }
  }
        
  public void testRepOk(){
    try{
      TableEntiers table = new TableEntiers(4);
      assertTrue(table.repOk());
      assertEquals(0, table.taille());
      assertTrue(table.repOk());
      table.ajouter(new Entier(0));
      assertEquals(1, table.taille());
      assertTrue(table.repOk());
      
      table.ajouter(new Entier(1));
      assertTrue(table.repOk());
      
      table.ajouter(new Entier(2));
      assertTrue(table.repOk());
      
      table.ajouter(new Entier(3));
      assertEquals(4, table.taille());
      assertTrue(table.repOk());
      // ...
      
    }catch(TableException exc){
      fail("Une exception n'est pas attendue ici ...");
    }
  }
  
  public void testAf(){
    try{
      TableEntiers table = new TableEntiers(4);
      List<Integer> liste = table.af();
      table.ajouter(new Entier(0));
      liste.add(new Entier(0).af());
      assertEquals(table.af(),liste);
      // ...
    }catch(TableException exc){
      fail("Une exception n'est pas attendue ici ...");
    }
  }
  
  public void testRepOkTailleNulle(){
    try{
      TableEntiers table = new TableEntiers(0);
      assertTrue(table.repOk());
      assertEquals(0, table.taille());
      
      assertEquals(true, table.estVide());
      assertEquals(true, table.estPleine());
      
      assertNotNull(table.iterator());
      assertFalse(table.iterator().hasNext());
      // ...
    }catch(Exception exc){
      fail("Une exception n'est pas attendue ici ...");
    }
  }
  
}

 

Post-liminaire : Préparation du tp3, exécution et tests de l'applette de l'énoncé

console> appletviewer http://jfod.cnam.fr/progAvancee/tp3/tp3.html
avec si nécessaire sous windows set PATH=D:\BlueJ-315\jdk\bin;%PATH%

Depuis votre navigateur http://jfod.cnam.fr/progAvancee/tp3/tp3.html


/* Une idée...