[Généricité] Un échec de compilation qui s'explique précisément par?
Bonjour,
J'écrivais un petit code de démonstration, et j'ai rencontré un obstacle inattendu.
Avec:
Code:
1 2 3
| public abstract class Fruit extends Produit implements Périssable {...}
et
public class Pomme extends Fruit {...} |
J'ai écrit ceci:
Code:
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:
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:
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:
1 2 3 4
| public Vector<Pomme> liste()
je dois simuler cette invocation:
Vector.add(Pomme p) |
Avec:
Code:
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:
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.