第一次发帖,标题很垃圾。 我正在尝试使用类型推断,但在使用工厂模式时很难让它正常工作,让我写一些代码来让它更清楚一点:
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 作为模板返回,因为它实现了模板?
谢谢!
编辑:事实上,我想要实现的工厂看起来像这样,而且似乎这就是类型推断存在的问题:
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 进行了很多测试,包括类型检查,所以现在必须这样做。
最佳答案
TemplateImpl
仅与 Template<ChildObject>
兼容, 所以 new TemplateImpl()
不能是 public <T extends ParentObject> Template<T> generate()
的有效返回值- 因为 T
可以是 ParentObject
的不同子类
最简单的更改是制作 Template
一个类:
private class Template<T extends ParentObject> {
void doSomething(T object){/*implement*/}
}
或者,如果它必须是一个接口(interface),则生成 TemplateImpl
也通用:
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>
,那么你的工厂方法不需要是通用的:
private class TemplateImpl implements Template<ChildObject> {
public void doSomething(ChildObject object) { }
}
//and the factory:
private class Factory {
public Template<ChildObject> generate() {
return new TemplateImpl(); //TemplateImpl is a Template<ChildObject>
}
}
应避免使用第二种解决方案,因为它使用原始类型。
关于Java:返回一个实现具有类型推断的接口(interface)的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56483486/