我有以下问题:
有一个通用的Factory接口
interface Factory<T> {
T create();
}
现在我有两个T1和T2类,其中T2是T1
的细化class T1 {
}
class T2 extends T1 {
}
和这两种类型的两家工厂:
interface T1Factory extends Factory<T1> {
public T1 create();
}
interface T2Factory extends Factory<T2> {
public T2 create();
}
对于这些工厂,将通过Generics提供默认实现:
class DefaultFactory<T, F extends Factory<T>> implements Factory<T> {
private F factory;
...
public T create()
{
return factory.create();
}
}
应该用于实现T1和T2的工厂。
class DefaultT1Factory extends DefaultFactory<T1,T1Factory> {
}
class DefaultT2Factory extends DefaultFactory<T2,T2Factory> {
}
到这里它工作正常。现在问题。 因为T2是T1的细化,所以T2的工厂也可以用作T1的工厂。
这要求T2Factory来自T1Factory。如果我这样做,我不能使用DefaultFactory类来实现DefaultT2Factory,因为T2Factory不是Factory&lt; T2&gt;。 如果我将此关系添加到T2Factory的extends子句,我得到的错误是接口Factory不止一次被使用。但我需要Factory接口才能在默认实现中使用create方法。
从方法签名的角度来看,一切都很好。因此,我将默认实现的实现复制到工厂实现中。在我的情况下,这个编码非常大,我想避免代码重复。
知道如何规避这个问题。
答案 0 :(得分:1)
我认为你的意思是
因为T2是T1的细化,所以T1的工厂也可以用作T2的工厂。 T1的工厂不应该用作T2的工厂,因为T1不是T2。但是T2是T1,因此T2的工厂可以安全地用作T1的工厂(或作为T1的工厂处理)
public interface T1Factory<J extends T1> extends Factory<T1> {
public T1 create();
}
现在,当你实现这个界面时,很酷的说法是
public class Foo implements T1Factory<T2> {
public T1 create(){
.....
}
}
现在基本上可以使用任何扩展或T1的类型参数化接口。在这种情况下,你说你想利用T2是一种T1关系。
希望有所帮助
答案 1 :(得分:0)
您可以使用wildcard来定义类似 Factory of T或任何T 子类型的内容。如果您将DefaultFactory
的签名更改为
class DefaultFactory<T, F extends Factory<? extends T>> implements Factory<T> {
然后你应该能够拥有DefaultFactory<T1, T2Factory>
。
答案 2 :(得分:0)
我想我找到了一个解决方案,不是很好,但它似乎有效。之前的答案几乎正常,但使用 super 而不是 extends 。 重要的是能够重用实现。
当使用super。
放宽工厂元素的类型约束时,这应该是可能的class DefaultFactory<T, F extends Factory<? super T>> {
private F factory;
@SuppressWarnings("unchecked")
public T create()
{
return (T)factory.create();
}
}
价格是调用create方法时不安全的类型,需要不安全的类型转换。但其余的似乎按预期工作。
T2Factory 因此必须扩展 T1Factory 。然而,遗憾的是它不是 Factory&lt; T2&gt; ,但这只是为了能够在默认实现中调用create方法返回正确的类型。为此目的,只需 Factory&lt; T1&gt; (这会导致所需的类型转换)。