Méthode générique Type Sécurité
Question
J'ai le concept de NodeType
s et Node
s. Un createInstance()
est un groupe de métadonnées à partir desquelles vous pouvez créer public Thing createInstance()
des instances (un peu comme toute la relation Classe / Objet).
J'ai différentes @SuppressWarnings("unchecked")
implémentations et diverses implémentations de nœuds.
Dans mon AbstractNodeType (niveau supérieur pour les NodeTypes), j'ai une méthode abstraite <=> qui, une fois implémentée par la sous-classe, crée l'instance de nœud appropriée:
public abstract class AbstractNodeType {
// ..
public abstract <T extends AbstractNode> T createInstance();
}
Dans mes <=> implémentations, j'implémente la méthode comme suit:
public class ThingType {
// ..
public Thing createInstance() {
return new Thing(/* .. */);
}
}
// FYI
public class Thing extends AbstractNode { /* .. */ }
Tout cela est bien beau, mais <=> crée un avertissement sur la sécurité du type. Plus précisément:
Type safety: Le type de retour Chose pour createInstance () du type ThingType nécessite une conversion non contrôlée se conformer à T du type AbstractNodeType
Qu'est-ce que je fais de mal pour provoquer un tel avertissement?
Comment puis-je reformuler mon code pour résoudre ce problème?
<=> n'est pas bon, je souhaite résoudre ce problème en le codant correctement, sans ignorer le problème!
La solution
Vous pouvez simplement remplacer <T extends AbstractNode> T
par AbstractNode
grâce à la magie des retours de covariant Java 5
ajouté de l'aide, mais il n'a pas reçu le pub qu'il méritait.
Autres conseils
Deux façons:
(a) N'utilisez pas de génériques. Ce n'est probablement pas nécessaire dans ce cas. (Bien que cela dépende du code que vous n'avez pas montré.)
(b) Générez AbstractNodeType comme suit:
public abstract class AbstractNodeType<T extends AbstractNode> {
public abstract T createInstance();
}
public class ThingType<Thing> {
public Thing createInstance() {
return new Thing(...);
}
}
Quelque chose comme ça devrait marcher:
interface Node{
}
interface NodeType<T extends Node>{
T createInstance();
}
class Thing implements Node{}
class ThingType implements NodeType<Thing>{
public Thing createInstance() {
return new Thing();
}
}
class UberThing extends Thing{}
class UberThingType extends ThingType{
@Override
public UberThing createInstance() {
return new UberThing();
}
}