Bonjour,


J'écrivais un petit code de démonstration, et j'ai rencontré un obstacle inattendu.

Avec:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
public abstract class Fruit extends Produit implements Périssable {...}
et
public class Pomme extends Fruit {...}

J'ai écrit ceci:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Expérimentation
{
   public <P extends Fruit> Vector<P> liste()
   {
      Vector<P> liste = new Vector<P>();
 
      Pomme pomme = new Pomme("Pomme rouge");
      liste.add(pomme);
 
      Fruit f = liste.get(0);
 
      return(liste);
   }
}
La compilation échoue sur un message "The method add(P) in the type Vector<P> is not applicable for the arguments (Pomme)".

Et pourtant, Pomme hérite bel et bien de Fruit!
Je peux essayer une grande variété d'instructions qui fonctionnent et qui le montrent:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
Fruit f = liste.get(0);
ou
Vector<? extends Fruit> liste = new Vector<Pomme>();

Mais le add(pomme) dans le vecteur, lui, ne passe pas.

Bien entendu, si je modifie le prototype de ma fonction en:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
public Vector<Pomme> liste()
ou
public Vector<Fruit> liste()
et que j'adapte son code en conséquence, tout rentrera dans l'ordre. Mais:
- Ce n'est pas ce que je veux.
- Cela ne me donnera pas pour autant l'explication du problème de compilation qui se pose.


J'ai fait l'hypothèse que ce qui empêche Java de compiler mon programme c'est qu'à la compilation il procède au type erasure pour rendre son code binairement compatible 1.4.

Et qu'alors, il se dit:

Avec:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
public Vector<Pomme> liste()
 
je dois simuler cette invocation:
Vector.add(Pomme p)
Avec:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
public Vector<Fruit> liste()
 
je dois simuler cette invocation:
Vector.add(Fruit f)
et dans les deux cas, je peux faire une assertion sur le paramètre d'entrée et le simplifier en un type unique.

Mais avec:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
public <P extends Fruit> Vector<P> liste()
 
je dois invoquer:
Vector.add(? extends Fruit f)
Et là, je ne peux pas remplacer ? extends Fruit par une classe unique puisque cela pourrait être n'importe quelle classe dérivée de Fruit.

Mais cette explication ne me convient pas entièrement, car ? extends Fruit est une expression qui admet Fruit comme classe.

Donc, Java devrait pouvoir faire l'assertion que la méthode add(...) à appeler a pour prototype minimal garanti: Vector.add(Fruit f)?


Quel explication donnez-vous à ce qui se produit?

Je vous remercie!

Grunt.