首次发布,抱歉,标题可能是垃圾。 我正在尝试使用类型推断,但是在使用工厂模式时努力使其正常工作,让我扔掉一些代码以使其更清晰:
private class ParentObject { }
private class ChildObject extends ParentObject { }
private interface Template<T extends ParentObject> {
void doSomething(T object);
}
private class TemplateImpl implements Template<ChildObject> {
public void doSomething(ChildObject object) { }
}
因此,我有一些从Template继承的类,它们对从ParentObject继承的对象做一些事情(我在本文中仅发布了其中一个)。 现在,我遇到的问题是,当我尝试生成这些模板类之一时,在尝试执行此操作时,我不断收到“不兼容的类型”错误:
private class Factory {
public <T extends ParentObject> Template<T> generate() {
return new TemplateImpl(); // here is the error
}
}
private class Service {
public <T extends ParentObject> void magic() {
Factory f = new Factory();
Template<T> a = f.generate();
}
}
或者当我这样做时,我收到“未经检查的分配”警告(代码按预期的方式工作,但是如果我做错了,我宁愿解决它!)
private class AlternativeFactory {
public Template generate() {
return new TemplateImpl();
}
}
private class Service {
public <T extends ParentObject> void magic() {
AlternativeFactory af = new AlternativeFactory();
Template<T> b = af.generate(); // warning here
}
}
有人对我如何在没有任何警告的情况下进行这项工作有任何见解吗?如果这是一个简单的类型,我还没有太多使用类型推断。 我不明白的是为什么我不能将TemplateImpl作为实现Template的模板返回?
谢谢!
编辑:实际上,我要实现的工厂看起来像这样,并且似乎这就是围绕类型推断的问题所在:
private class Factory {
public Template<T extends ParentObject> generate(int option) {
switch (option) {
case 1:
return new TemplateA(); // implements Template<A> where A extends ParentObject
case 2:
return new TemplateB(); // implements Template<B> where B extends ParentObject
default:
throw new IllegalArgumentException();
}
}
}
编辑:决定使用我上面提供的代码(AlternativeFactory),并在调用工厂的服务方法中使用SuppressWarnings,因为看来我希望实现的目标是不可能的。我知道这使用的是原始类型,是一种不好的做法,但是我围绕这些Template对象和AlternativeFactory进行了很多测试,包括类型检查,因此现在必须这样做。
答案 0 :(得分:6)
TemplateImpl
仅与Template<ChildObject>
兼容,因此new TemplateImpl()
不能是public <T extends ParentObject> Template<T> generate()
的有效返回值-因为T
可以是{的另一个子类{1}}
最简单的更改是使ParentObject
为一类:
Template
或者,如果必须是接口,则也使private class Template<T extends ParentObject> {
void doSomething(T object){/*implement*/}
}
通用:
TemplateImpl
这将允许您的工厂使用type参数:
private class TemplateImpl<T extends ParentObject> implements Template<T> {
public void doSomething(ChildObject object) { }
}
如果您需要确保private class Factory {
public <T extends ParentObject> Template<T> generate() {
return new TemplateImpl<T>(); //T is not bound to ChildObject
}
}
仅以TemplateImpl
的身份使用,则您的工厂方法不需要是通用的:
Template<ChildObject>
应避免使用第二种解决方案,因为它使用的是原始类型。
答案 1 :(得分:2)
您的错误是TemplateImpl不是通用的。它已经有一个定义。然后您对generate()方法进行了参数化。 TemplateImpl被迫使用ChildObject,而您的generate()则返回扩展Parent的“内容”。您可以将return语句强制转换为Template。