Segurança do tipo de método genérico
Pergunta
Eu tenho o conceito de NodeType
areia Node
S.A NodeType
é um monte de metadados que você pode criar Node
instâncias de (muito parecido com todo o relacionamento Classe/Objeto).
eu tenho vários NodeType
implementações e várias implementações de Node.
No meu AbstractNodeType (nível superior para NodeTypes) eu tenho um resumo createInstance()
método que irá, uma vez implementado pela subclasse, criar a instância correta do Node:
public abstract class AbstractNodeType {
// ..
public abstract <T extends AbstractNode> T createInstance();
}
No meu NodeType
implementações eu implemento o método assim:
public class ThingType {
// ..
public Thing createInstance() {
return new Thing(/* .. */);
}
}
// FYI
public class Thing extends AbstractNode { /* .. */ }
Está tudo muito bem, mas public Thing createInstance()
cria um aviso sobre segurança de tipo.Especificamente:
Digite segurança:A coisa do tipo de retorno para CreateInstance () do tipo ThingType precisa de conversão desmarcada para estar em conformidade com o tipo de abstraçãoNodEType
O que estou fazendo de errado para causar tal aviso?
Como posso refatorar meu código para corrigir isso?
@SuppressWarnings("unchecked")
não é bom, desejo corrigir isso codificando corretamente, sem ignorar o problema!
Solução
Você pode simplesmente substituir <T extends AbstractNode> T
com AbstractNode
graças à magia da covariantes retornos . Java 5
suporte adicional, mas não recebeu o pub que merecia.
Outras dicas
Duas maneiras:
(a) Não use genéricos. Provavelmente não é necessário neste caso. (Apesar de que depende o código havn't mostrado.)
(b) Generify AbstractNodeType como se segue:
public abstract class AbstractNodeType<T extends AbstractNode> {
public abstract T createInstance();
}
public class ThingType<Thing> {
public Thing createInstance() {
return new Thing(...);
}
}
Algo assim deve 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();
}
}