1 commentaires samedi 10 octobre 2009

Dans le .NET Framework, on retrouve l'interface IEnumerable (ainsi que sa version générique, IEnumerable<T> depuis la version 2.0). Toute classe implémentant cette interface pourra être parcourue avec un foreach.

Java possède, depuis sa version 1.5, un équivalent, l'interface Iterable. Une classe implémentant Iterable pourra être parcourue avec un for.

En C#, j'ai tendance à utiliser le plus possible IEnumerable: c'est le dénominateur commun. Alors quand je me suis mis à faire du Java, j'ai décidé d'employer Iterable pour les mêmes raisons. Sauf que j'ai découvert quelque chose d'étrange.

Avec .NET, les tableaux implémentent IEnumerable. On peut donc passer un tableau à une méthode qui attend un IEnumerable en paramètre. Or, en Java, les tableaux n'implémentent pas Iterable. On peut les parcourir comme un Iterable, mais c'est probablement du à une "patch" du compilateur. Je n'ai aucune idée de pourquoi est-ce que c'est le cas, mais toujours est-il qu'on ne peut donc pas faire la même chose qu'avec .NET.

Mais ce n'est pas vraiment un problème. Il suffit de coder un adaptateur! Et c'est ce que j'ai fait:

  1. import java.util.Iterator;  
  2. import java.util.NoSuchElementException;  
  3.   
  4. /** 
  5.  * Un adaptateur permettant d'utiliser un tableau là où un Iterable<T> est requis 
  6.  * @author Etienne de Martel 
  7.  * @param <T> Le type d'un élément du tableau 
  8.  */  
  9. public class IterableArray<T> implements Iterable<T>  
  10. {  
  11.     // Un itérateur sur un tableau  
  12.     private class ArrayIterator implements Iterator<T>  
  13.     {  
  14.         T[] _array;  
  15.         int _index;  
  16.     
  17.         public ArrayIterator(T[] array)  
  18.         {  
  19.             _array = array;  
  20.             _index = 0;  
  21.         }  
  22.     
  23.         @Override  
  24.         public boolean hasNext()   
  25.         {  
  26.             return _index < _array.length;  
  27.         }  
  28.   
  29.         @Override  
  30.         public T next()   
  31.         {  
  32.             if(!hasNext())  
  33.                 throw new NoSuchElementException();  
  34.             return _array[_index++];  
  35.         }  
  36.   
  37.         // Cet itérateur est en lecture seule  
  38.         @Override  
  39.         public void remove()   
  40.         {  
  41.             throw new UnsupportedOperationException();  
  42.         }  
  43.     
  44.     }  
  45.    
  46.     private T[] _array;  
  47.    
  48.     /** 
  49.      * Construit un nouvel adaptateur 
  50.      * @param array Le tableau autour duquel l'adaptateur sera construit 
  51.      * @throws NullPointerException Le tableau passé en paramêtre est null 
  52.      */  
  53.     public IterableArray(T[] array) throws NullPointerException  
  54.     {  
  55.         if(array == null)  
  56.             throw new NullPointerException("array cannot be null");  
  57.         _array = array;  
  58.     }  
  59.    
  60.     @Override  
  61.     public Iterator<T> iterator()   
  62.     {  
  63.         return new ArrayIterator(_array);  
  64.     }  
  65.    
  66. }  


Voilà. Have fun.