Etant donné un type générique Result<T>
avec la mise en œuvre partielle suivanteJava - entrée générique Délimitée à méthode générique limitée
public class Result<T> {
/* fields, ctor, etc... */
public Result<T> mergeWith(Result<? extends T> other) {
/* fiddle with this and other (acting as producer) and return */
}
/* other methods */
}
et l'utilisation de celui-ci dans un visiteur ...
Interface:
public interface Visitor<T> {
T visitFile(FileContext ctx);
T aggregate(T left, T right);
/* ... */
}
Mise en œuvre:
public class SomeVisitor implements Visitor<Result<? extends Node>> {
// this works fine, as I can return subtypes of 'Node'
@Override
public Result<FileNode> visitFile() { }
/* ... */
@Override
public Result<? extends Node> aggregate(Result<? extends Node> left,
Result<? extends Node> right) {
// This line completely blows up.
Result<? extends Node> tempResult = left.mergeWith(right);
// Expected type: 'Option<? extends capture of ? extends Node>'
// Have type: 'Option< ? extends Node>'
}
callsite de SomeVisitor
:
FileContext fileCtx = someOtherService.acquireFileContext();
SomeVisitor visitor = new SomeVisitor();
Result<FileNode> fileNodeResult = visitor.visitFile(fileCtx);
// process the result
L'exemple ci-dessus échoue avec les messages d'erreur de type discordance donné.
J'ai déjà essayé de changer la signature de .mergeWith pour accepter le beaucoup plus étroit Result<T>
au lieu d'un Result<? extends T>
. Cela conduit à un type attendu de Result<capture of ? extends Node>
dans cet exemple. Et le casser dans d'autres endroits, où <? extends T>
est le type générique correct, puisque other
est un producteur dans ce cas.
La seule solution qui fonctionne réellement, est renversons les deux left
et right
-Result<Node>
, les fusionner, puis retourner:
@SuppressWarnings("unchecked")
Result<Node> tempLeft = (Result<Node>) left;
@SuppressWarnings("unchecked")
Result<Node> tempRight = (Result<Node>) right;
Result<Node> tempResult = tempLeft.mergeWith(tempRight);
Non seulement est que laid et introduit des variables temporaires, il est également de ne pas obtenir plus jolie quand Je joins les moulages.
Je voudrais savoir si c'est juste la vérité laide sur les génériques Java et la limite de ceux-ci ou si je fais quelque chose de mal.
Pouvez-vous afficher la signature 'Visitor.visitFile()'? En outre, cela aiderait à montrer comment 'SomeVisitor' est réellement utilisé. – shmosel
@shmosel fait. J'espère que cela aide. – baeda