真正的Java泛型专家有点困惑…;)
假设我有以下两个接口:
interface Processor { void process(Foo foo); } interface Foo { Processor getProcessor(); }
例如,以下两个实现类:
static class SomeProcessor implements Processor { static final SomeProcessor INSTANCE = new SomeProcessor(); @Override public void process(Foo foo) { if (foo instanceof SomeFoo) { // <-- GET RID OF THIS ? // process ((SomeFoo) foo) } } } class SomeFoo implements Foo { @Override public Processor getProcessor() { return SomeProcessor.INSTANCE; } }
有什么方法可以使这两个接口通用,以至于我不需要instanceof在process()函数中进行标记检查,而在我的代码的其他地方仍可以进行以下构造工作?
instanceof
process()
foo.getProcessor().process(foo);
(当然,我不知道我在处理哪个Foo子类)
换句话说:我正在寻找一种在对象中定义函数的方法,使其只能返回另一个对象,该对象处理包含该函数的对象的类型。注意:我不仅在谈论处理包含该函数的对象的某些最小公分母超类(上方:Foo),而且还涉及该对象的实际类(上方:SomeFoo)。
(除非我现在真的很愚蠢,否则这听起来似乎微不足道)。
这比我想的还要丑。我的看法:
interface Processor<F extends Foo<F>> { void process(F foo); } interface Foo<F extends Foo<F>> { Processor<F> getProcessor(); } interface SomeFoo extends Foo<SomeFoo> { @Override SomeProcessor getProcessor(); } interface SomeProcessor extends Processor<SomeFoo> { @Override void process(SomeFoo foo); }
现在,将编译以下内容:
<F extends Foo<F>> void process(F foo) { foo.getProcessor().process(foo); }
但
void process(Foo<?> foo) { foo.getProcessor().process(foo); }
不会,因为编译器无法知道所传递的foo的实际类型是其类型参数的子类型,就像有人可以这样写:
class Bar implements Foo<SomeFoo> { ... }
我们可以通过要求foo的子类型实现对其类型参数的转换来解决此问题:
abstract class Foo<F extends Foo<F>> { abstract Processor<F> getProcessor(); abstract F getThis(); } class SomeFoo extends Foo<SomeFoo> { @Override SomeFoo getThis() { return this; } @Override Processor<SomeFoo> getProcessor() { return new SomeProcessor(); } }
现在,我们可以写:
<F extends Foo<F>> void process(Foo<F> foo) { foo.getProcessor().process(foo.getThis()); }
并用
Foo<?> foo = ...; process(foo);
为了易于使用,我建议将helper方法移到Foo类中:
abstract class Foo<F extends Foo<F>> { abstract Processor<F> getProcessor(); abstract F getThis(); void processWith(Processor<F> p) { p.process(getThis()); } }
更新:我认为newaccts更新的答案显示了一个更优雅的解决方案,因为它不需要递归类型界限。