Comment puis-je résoudre ambigu méthodes causée par intersection types en Java génériques?
Je viens de découvrir que vous pouvez spécifier plusieurs types dans un seul type de paramètre lié (voir l'exemple). Comme tout nouvel outil, j'ai essayé d'explorer les possibilités de comment cela peut être utilisé (et détourné). J'ai conçu cet exemple pour illustrer.
Sur l'exemple ci-dessous, le compilateur me donne une erreur
expédition(nouveau AlphabetSoup());
La méthode d'envoi(en Démo.Soupe) est ambigu pour le type de Démo
Je peux le comprendre, soit parce que la signature de la méthode correspond. Ma question est comment cela pourrait-il être résolu sans changer les méthodes? Si j'ai voulu forcer un appel à la Soupe version je pourrais abattu à la Soupe:
expédition((Soupe) de nouvelles AlphabetSoup())
Mais je n'en suis pas sûr comment vous pouvez forcer un appel à l'autre version. Est-il possible?
public class Demo {
interface HasA { public char getA(); }
interface HasB { public char getB(); }
interface HasC { public char getC(); }
interface Soup {
public void eat();
}
class Alphabet implements HasA, HasB, HasC {
public char getA() { return 'a'; }
public char getB() { return 'b'; }
public char getC() { return 'c'; }
}
class AlphabetSoup implements Soup, HasA, HasB, HasC {
public void eat() { System.out.println("Mmm Mmm Good!"); }
public char getA() { return 'a'; }
public char getB() { return 'b'; }
public char getC() { return 'c'; }
}
public void dispatch(Soup soup) {
System.out.println("Eating some soup...");
soup.eat();
}
public <T extends HasA & HasB & HasC> void dispatch(T letters) {
System.out.println("Reciting ABCs...");
System.out.println(letters.getA());
System.out.println(letters.getB());
System.out.println(letters.getC());
}
public void test() {
dispatch(new Alphabet());
dispatch(new AlphabetSoup());
}
public static void main(String[] args) {
new Demo().test();
}
}
--
Edit: Juste appris que "plusieurs délimitée paramètres de type sont officiellement dénommé "Intersection" Types de
- Je crois que la seule façon possible d'appeler l'autre méthode dispatch est par l'aide de la réflexion.
Vous devez vous connecter pour publier un commentaire.
Remarque que l'erreur n'est pas liée aux médicaments génériques, vous obtenez le même résultat si vous utilisez des interfaces et un type est l'intersection:
Vous obtenez la même erreur dans les "doSomething", le compilateur ne peut pas résoudre l'ambiguïté. Voulez-vous de les interpréter en tant que XX ou YY? Vous devez le spécifier avec un cast.
Mais si vous avez une hiérarchie, comme "YY s'étend XX" et "XY implémente YY", le compilateur peut déduire de la bonne méthode à appeler.
Le compilateur est à droite, et vous permet d'économiser de gâchis.
AlphaBetSoup est un sous-type de la soupe et aussi un sous-type de HasA, HasB, et HasC
Par conséquent, il correspond à la facture pour les deux versions de l'Expédition
Depuis la Soupe n'est pas un sous-type de HasA, HasB, ou HasC, il a également ne peut pas dire qu'une version est plus "précis" que les autres.
Par conséquent, vous obtiendrez l'erreur correctement.
Méthode surchargée ne doit pas être ambigu. Si vous avez un type qui mélange les deux types et vous avez eu une surcharge pour chaque, changement de votre hiérarchie ou de se débarrasser d'une surcharge. C'est de la mauvaise utilisation de sous-typage et de la surcharge.
Laissez-moi vous expliquer cela avec un programme très simple:
Code ci-dessous illustre couse de La méthode est ambigu pour le type d'erreur du compilateur.
Le problème est maintenant évidente: puisque Chaîne implémente à la fois Comparables et
Serializable, le compilateur ne peut pas savoir quelle méthode vous avez l'intention de faire appel.
Une distribution simple à résoudre le problème:
ambiguousMethod((Comparables),"bar");
http://www.javaneverdie.com/java/the-method-is-ambiguous-for-the-type/
Dans notre cas, la méthode d'expédition est créé le problème. Voir
et
maintenant, si vous appelez
dispatch(new AlphabetSoup());
compilateur de confusion quant à la version de l'expédition doit être appelé ?Remarque que vous n'avez pas un réel problème, que les méthodes que vous êtes intéressé à l'appelant sont déjà appelé en raison de liaison dynamique.
De course
dispatch((Soup) new AlphabetSoup());
rendements:Par conséquent, la
AlphabetSoup
méthode sont déjà appelé en raison de base, le comportement polymorphique.Pas que vous devriez garder la surcharge
dispatch
méthode (je upvoted Uri pour cette raison), mais vous pouvez forcer la version générique d'être appelé par essayer:ou appelez la soupe version avec:
La meilleure façon de contourner ce problème, cependant, est de ne pas avoir la surcharge
dispatch
méthode en premier lieu.