1

salut, j'ai un pb avec la definition des mes iterators avec les enhanced for loops du J2SE 1.5 (les boucles foreach)


IterableClass.java
import java.util.Iterator;
import java.util.LinkedList;


public class IterableClass
	implements Iterable
{
	public IterableClass()
	{
		lt= new LinkedList<Integer>() ;
		lt.add(1) ;
		lt.add(2) ;
		lt.add(3) ;
	}
	public Iterator<Integer> iterator()
	{
		return lt.iterator() ;
	}
	private LinkedList<Integer> lt ;
}





Main.java
import java.util.Iterator;


public class Main
{

	/**
	 * @param args
	 */
	public static void main( String[] args )
	{
		IterableClass ic= new IterableClass() ;
		
		// V1 : compile et fonctionne :)
		System.out.println("V1 :") ;
		for ( Iterator iter= ic.iterator() ; iter.hasNext() ; ) {
			Integer e= (Integer)iter.next() ;
			System.out.println(e.toString()) ;
		}
		// V2 : compile et fonctionne :)
		System.out.println("V2 :") ;
		for ( Iterator<Integer> iter= ic.iterator() ; iter.hasNext() ; ) {
			Integer e= iter.next() ;
			System.out.println(e.toString()) ;
		}
		// V3 : ne compile même pas ! #rage#
		System.out.println("V3 :") ;
		for ( Integer i : ic )
			System.out.println(i.toString()) ;
	}

}


[IMG]http://img480.imageshack.us/img480/9886/pbiterator9ny.png[/IMG]


le problème se situe dans la version 3, elle refuse de compiler, alors qu'il me semble pourtant que c'est théoriquement équivalent à l'écriture de la version 2.... si vous avez une idée, je suis preneur... chapo

2

j'y connais rien en java, mais il ne manque pas une "{" ici ?

// V3 : ne compile même pas ! rage
System.out.println("V3 :") ;
for ( Integer i : ic )
System.out.println(i.toString()) ;
}


edit : nan, j'ai rien dit, c'est pas au même niveau

3

Essaie

public class IterableClass implements Iterable <Integer>

par curiosite ;P

4

ah oui tiens, je vais tester dans une seconde hehe (mmm, tu as édité tongue)

..
..
....

5

youhouuuuuuu, ça fonctionne ! (quel boulet je fais..)

merci beaucoup ! trilove

(j'avais bien l'intuition que le compilo ne devinait pas le type de l'iterator à instancier, mais je n'avais pas vu mon erreur..)

6

wink

Oue c'est assez chiant la genericite par erasure. :/

7

Sauf ton respect Pen^2, l'erreur était assez évidente cette fois-ci ( et le message d'erreur très clair) tongue
Je trouve personnellement que la généricité est le meilleur apport de Java 5 (c'est pas un troll, c'est une remarque smile).
Cinq font un et un font cinq : le tout est UNITE.
C'est dans l'incompréhension que je suscite que je trouve ma raison d'être.
Je suis moi, et je le suis parce que les autres ne le sont pas, et que ce sont eux qui forment ma personne.
Inconscience et déraison sont source d'imagination.
Au delà de ma conscience et de mon inconscient, mes rêves créent la réalité.

8

ben oui, c'est vrai, que veux tu que je te dise tongue (m'enfin j'ai pas encore tous les bon reflexes (et puis je ne suis pas certifié moa sad))

Sinon oui, la généricité c'est très bien, mais c'est dommage qu'ils n'aient pas ajouté les typedef pour l'occasion sad

9

typedef ? C'est à dire ? Donner un alias à une classe ? Pourrais tu stp me donner un exemple smile

Et pour répondre à skweek, c'est vrai que je n'ai pas étudié le sujet à fond, mais il me semble que la généricité par erasure a l'avantage de ne pas alourdir le java natif, tout en garantissant une robustesse à tout épreuve du fait de la rigueur du compilo. (l'inconvénient étant tout de même comme on l'a vu, de ne pas trop savoir où est l'erreur s'il y a une grande quantité de code générique)
Cinq font un et un font cinq : le tout est UNITE.
C'est dans l'incompréhension que je suscite que je trouve ma raison d'être.
Je suis moi, et je le suis parce que les autres ne le sont pas, et que ce sont eux qui forment ma personne.
Inconscience et déraison sont source d'imagination.
Au delà de ma conscience et de mon inconscient, mes rêves créent la réalité.

10

Enfin bon, ça n'empêche pas que le compilateur pourrait se permettre de donner des messages explicites, qu'il y'ait de la pré-traduction de code c'est son problème (d'autant plus qu'Eclipse intègre son propre compilateur).
[edit] typo

11

Ce qui est surtout bizarre, c'est le "<Object>" qui est sous-entendu par défaut... Perso ne connaissant pas Java 1.5 j'ai pas compris tout de suite pourquoi ça fonctionnait pas, étonnant donné que Object n'apparaît nulle part dans le code ^^ (enfin c'est vrai qu'ils sont un peu obligés pour la rétrocompatibilité, je crois que C# 2.0 gère ça en définissant des nouveaux noms de classes pour les types génériques standard, c'est pas terrible non plus... c'est quand même hallucinant que la généricité ait pas été prévue dès le départ embarrassed)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

12

Le object est normal, c'est un reste du passé. Le compilo s'amuse lui tout seul a gerer les casts. C'est plus securisant, d'un cote car le compilo s'assure que "le code est bon" par rapport au typage....

13

Pollux
: Perso ne connaissant pas Java 1.5 j'ai pas compris tout de suite pourquoi ça fonctionnait pas, étonnant donné que Object n'apparaît nulle part dans le code ^^

En décompilant la V3 valide on a :
        System.out.println("V3 :");
        Integer i;
        for(Iterator iterator = ic.iterator(); iterator.hasNext(); System.out.println(i.toString()))
            i = (Integer)iterator.next();

En virant (Integer) voilà l'Object smile
Pollux
: enfin c'est vrai qu'ils sont un peu obligés pour la rétrocompatibilité

Peut-être aussi que c'est plus simple de mettre en place du pre-processing que de revoir la JVM...

14

Argl, donc t'es en train de me dire que Iterator<Integer> est juste un sucre syntaxique et pas une vraie classe distincte de Iterator ? couic Donc il est considéré comme un sous-type de Iterator ? Donc il n'y a aucune garantie qu'un Iterator<Integer> contiendra réellement des entiers, et donc on ne sait même pas si lire un élément du tableau risque de provoquer une exception ou non ? couic2 (i.e. on n'a pas de sûreté du typage, alors qu'on ne fait aucun cast explicite...)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

15

Oui, c'est ce que swkeek disait par "genericite par erasure".
Pollux :
Donc il n'y a aucune garantie qu'un Iterator<Integer> contiendra réellement des entiers

Au runtime non, mais à la compilation tout est correctement vérifié.

16

Le compilo java sort un warning à la compilation s'il n'est pas capable de statiquement vérifier un cast. Mais en l'absence de tel warning, je crois que le typage est "safe and sound".
avatar
I'm on a boat motherfucker, don't you ever forget

17

edit: rien

18

Moumou>
Euh, je comprends pas confus

Si je fais :
void f(Iterator i) { i[0] = "hello"; }
int g() {
  Iterator<Integer> i = tableau.iterator();
  f(i);
  return i[0];
}

le warning qui dit qu'il est pas capable de vérifier statiquement et que donc il pourrait y avoir une exception, il est sur quelle ligne ?

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

19

Ca devrait te donner un truc du genre :
% javac Foo.java
Note: Foo.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.
avatar
I'm on a boat motherfucker, don't you ever forget

20

nan mais concrètement qu'est-ce qui pose problème : c'est l'appel de f ? (et à ce moment-là Iterator<Integer> n'est pas vraiment un sous-type de Iterator) ou c'est autre chose ?

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

21

Je viens de me rappeler comment ça marche (ça fait un an que j'ai pas fait de java).

En fait, Iterator<Integer> n'est effectivement pas un sous type de Iterator. Et donc effectivement le fait d'appeler f sur i n'est pas vérifiable, et tu auras un warning. En revanche, il existe des types polymorphes Iterator<E> (E est une variable de type), qui te permettent de faire un truc du genre :

bool f(Iterator<E> i) { return i.hasNext(); } 
Integer g() { 
  Iterator<Integer> i = tableau.iterator();
  if (f(i)) { 
    return i.next();
  } else {
    return (Integer)0;
}


Ca, aux erreurs près, c'est type-checkable.
avatar
I'm on a boat motherfucker, don't you ever forget

22

Ah oui en fait "Iterator" tout court est un raw type, et n'est pas synonyme de Iterator<Object>... D'ailleurs, ils disent qu'ils pourront le supprimer dans une prochaine version ^^

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

23

S'il n'y aucun warning à la compilation, il n'y aura aucune erreur de typage à l'exécution, c'est le contrat de sun.
enfin c'est vrai qu'ils sont un peu obligés pour la rétrocompatibilité

Hélas, java 5 n'est pas 100% rétrocompatible.
Argl, donc t'es en train de me dire que Iterator<Integer> est juste un sucre syntaxique et pas une vraie classe distincte de Iterator ?

Toutes les nouveautés sont des sucres syntaxiques, et ne sont pas reconnues dans le java natif.
Cinq font un et un font cinq : le tout est UNITE.
C'est dans l'incompréhension que je suscite que je trouve ma raison d'être.
Je suis moi, et je le suis parce que les autres ne le sont pas, et que ce sont eux qui forment ma personne.
Inconscience et déraison sont source d'imagination.
Au delà de ma conscience et de mon inconscient, mes rêves créent la réalité.

24

smeet :
typedef ? C'est à dire ? Donner un alias à une classe ?

Oui, c'est ce que je voulais dire.

Pourrais tu stp me donner un exemple smile


Je vois plusieurs raisons pour lesquelles ça serait utile
[ul]
[li] déjà, les generics c'est très bien, mais ça fait des noms de types assez rapidement longs à écrire (manifestement je ne suis pas le seul à penser ça : http://www.ibm.com/developerworks/library/j-jtp02216.html )
[li] ça peut être intéressant de cacher le véritable type d'une donnée à un utilisateur d'une classe : l'accesseur pourrait retourner un type en rapport avec la classe dans laquelle il est codé, pas un Vector<LinkedList<HashMap<Integer, String>> (triso)
[/ul]

25

Ben tu encapsules ton type dans une classe, et c'est gagné, non ?
avatar
I'm on a boat motherfucker, don't you ever forget

26

Et bien ça me semble possible via un petit héritage. J'avais déjà fait ça sur mon projet précédent oui

public class MonVector extends Vector<LinkedList<HashMap<Integer, String>> {

}

Par contre, le gros inconvénient est que tu ne bénéficies plus par défaut de tous les constructeurs de Vector.
Bon, à vérifier/peaufiner.
Cinq font un et un font cinq : le tout est UNITE.
C'est dans l'incompréhension que je suscite que je trouve ma raison d'être.
Je suis moi, et je le suis parce que les autres ne le sont pas, et que ce sont eux qui forment ma personne.
Inconscience et déraison sont source d'imagination.
Au delà de ma conscience et de mon inconscient, mes rêves créent la réalité.

27

(cross^de 9 minutes ^^)
Cinq font un et un font cinq : le tout est UNITE.
C'est dans l'incompréhension que je suscite que je trouve ma raison d'être.
Je suis moi, et je le suis parce que les autres ne le sont pas, et que ce sont eux qui forment ma personne.
Inconscience et déraison sont source d'imagination.
Au delà de ma conscience et de mon inconscient, mes rêves créent la réalité.

28

Moumou > si, en gros, mais c'est quand même pas tout à fait équivalent (si tu veux acceder aux méthodes, tu dois les recoder pour appeler celles de l'objet encapsulé, et puis bon au niveau de la conception, je trouve que c'est moyen d'ajouter une classe pour ça)

29

Pen^2 :
si tu veux acceder aux méthodes, tu dois les recoder pour appeler celles de l'objet encapsulé

oui enfin si tu veux pouvoir accéder à *toutes* les méthodes, autant utiliser le vrai type. Faire un alias, c'est justement pour dire que ce n'est pas vraiment la même chose (même si c'est représenté pareil), donc qu'on ne peut pas faire exactement la même chose avec.
Pen^2 :
et puis bon au niveau de la conception, je trouve que c'est moyen d'ajouter une classe pour ça

Ben, tout est une classe, en java, ce serait un peu dommage d'ajouter un truc différent juste pour ça smile
avatar
I'm on a boat motherfucker, don't you ever forget

30

Moumou :
Ben tu encapsules ton type dans une classe, et c'est gagné, non ?

C'est gagné seulement quand tu as besoin d'un sous-type, pas quand tu as besoin d'un sur-type... (i.e. tu peux pas t'en servir comme raccourci pour les paramètres d'une fonction)


D'ailleurs c'est marrant, le Java n'a pas une inférence de type bottom-up :
public static <K,V> Map<K,V> newHashMap() {
return new HashMap<K,V>();
}

You can use it to safely avoid entering the type parameters twice:
Map<Socket, Future<String>> socketOwner = Util.newHashMap();
i.e. le fait que l'appel soit stocké dans un Map<Socket, Future<String>> change la sémantique de l'appel fou2 (bon en fait heureusement tout se passe bien parce qu'aucun ClasseGénérique<U> ne peut être un sur-type strict de ClasseGénérique<String>, sauf si U est un wildcard smile en revanche ça exclut toute possibilité de conversion automatique entre classes dans une révision future de Java...)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)