Безопасность общего типа метода
Вопрос
У меня есть концепция NodeType
ы и Node
s.A NodeType
это набор метаданных, которые вы можете создать Node
экземпляры из (очень похоже на отношения между классом и объектом в целом).
У меня есть различные NodeType
реализации и различные реализации узлов.
В моем AbstractNodeType (верхний уровень для типов узлов) У меня есть ab abstract createInstance()
метод, который после реализации подклассом создаст правильный экземпляр узла:
public abstract class AbstractNodeType {
// ..
public abstract <T extends AbstractNode> T createInstance();
}
В моем NodeType
реализации Я реализую метод следующим образом:
public class ThingType {
// ..
public Thing createInstance() {
return new Thing(/* .. */);
}
}
// FYI
public class Thing extends AbstractNode { /* .. */ }
Все это прекрасно, но public Thing createInstance()
создает предупреждение о безопасности типов.В частности:
Безопасность типа:Возвращаемый тип Thing для CreateInstance() из типа ThingType нуждается в непроверенном преобразовании для соответствия T из типа AbstractNodeType
Что я делаю не так, чтобы вызвать такое предупреждение?
Как я могу перефакторизовать свой код, чтобы исправить это?
@SuppressWarnings("unchecked")
это нехорошо, я хочу исправить это, правильно закодировав его, а не игнорируя проблему!
Решение
Вы можете просто заменить <T extends AbstractNode> T
с AbstractNode
благодаря волшебству ковариантные возвраты. Java 5
добавлена поддержка, но она не получила той поддержки, которой заслуживала.
Другие советы
Два способа:
(а) Не используйте дженерики.Вероятно, в данном случае в этом нет необходимости.(Хотя это зависит от кода, который вы не показали.)
(b) Обобщите AbstractNodeType следующим образом:
public abstract class AbstractNodeType<T extends AbstractNode> {
public abstract T createInstance();
}
public class ThingType<Thing> {
public Thing createInstance() {
return new Thing(...);
}
}
Что-то подобное должно сработать:
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();
}
}