Seguridad del tipo de método genérico
Pregunta
tengo el concepto de NodeType
arena Node
s.A NodeType
es un montón de metadatos que puedes crear Node
instancias de (muy parecido a toda la relación Clase/Objeto).
tengo varios NodeType
implementaciones y varias implementaciones de Node.
En mi AbstractNodeType (nivel superior para NodeTypes) tengo ab abstract createInstance()
método que, una vez implementado por la subclase, creará la instancia de Nodo correcta:
public abstract class AbstractNodeType {
// ..
public abstract <T extends AbstractNode> T createInstance();
}
En mi NodeType
implementaciones Implemento el método de esta manera:
public class ThingType {
// ..
public Thing createInstance() {
return new Thing(/* .. */);
}
}
// FYI
public class Thing extends AbstractNode { /* .. */ }
Todo esto está muy bien, pero public Thing createInstance()
crea una advertencia sobre la seguridad de tipos.Específicamente:
Tipo de seguridad:El tipo de retorno de createInStance () desde el tipo de typing tytype necesita una conversión sin control para ajustar a t desde el tipo abstractNodeType
¿Qué estoy haciendo mal para provocar tal advertencia?
¿Cómo puedo refactorizar mi código para solucionar este problema?
@SuppressWarnings("unchecked")
no es bueno, deseo solucionarlo codificándolo correctamente, sin ignorar el problema.
Solución
Puedes simplemente reemplazar <T extends AbstractNode> T
con AbstractNode
gracias a la magia de rendimientos covariantes. Java 5
añadió apoyo, pero no recibió la publicidad que merecía.
Otros consejos
Dos caminos:
(a) No utilice genéricos.Probablemente no sea necesario en este caso.(Aunque eso depende del código que no hayas mostrado).
(b) Genere AbstractNodeType de la siguiente manera:
public abstract class AbstractNodeType<T extends AbstractNode> {
public abstract T createInstance();
}
public class ThingType<Thing> {
public Thing createInstance() {
return new Thing(...);
}
}
Algo así debería funcionar:
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();
}
}