我想要一个像这样的抽象Java类:
abstract class AbstractFoo<F extends AbstractFoo<F, L>, L extends FooListener<F, L>> {
private final Class<L> listenerClass;
protected AbstractFoo(Class<L> listenerClass) {
this.listenerClass = listenerClass;
}
interface FooListener<F extends AbstractFoo<F, L>, L extends FooListener<F, L>> {
void callback(F foo);
}
// Bar might implement FooListener, but I don't control it,
// so I have no guarantee
public void externalMethod(Bar bar) {
if (listenerClass.isInstance(bar)) {
L listener = listenerClass.cast(bar);
listener.callback(this); // does not compile
}
}
}
listener.callback(this);
无法编译,因为不能保证this
与F
的类型相同。能否以某种方式保证F
是this
的超类型?
答案 0 :(得分:1)
您想要做的是使用泛型在Java中模拟SELF类型。有关某些方法,请参见this link或a different site。但是,例如,无法强制F(或SELF类型)实际上是同一类型(请参见ConcreteFoo2的类型参数):
static class Bar implements FooListener<ConcreteFoo, Bar> {
@Override
public void callback(final ConcreteFoo foo) {
// TODO Auto-generated method stub
}
}
static class ConcreteFoo2 extends AbstractFoo<ConcreteFoo, Bar> {
protected ConcreteFoo2(final Class<Bar> listenerClass) {
super(listenerClass);
}
}
static class ConcreteFoo extends AbstractFoo<ConcreteFoo, Bar> {
protected ConcreteFoo(final Class<Bar> listenerClass) {
super(listenerClass);
}
}
除了继续采取这种方式,我首先考虑一下导致您来到这里的设计选择:
听众真的需要了解具体的课程吗?
AbstractFoo是否真的需要知道侦听器类的具体实现?
也许解决方案实际上是更少的类型参数,仅依赖于接口。
编辑:如果不想强制转换(F) this
,一个可能的解决方案是提供一种抽象方法protected abstract F getSelf();
,具体实现可通过返回this
来实现。
例如,请参见以下简化代码:
static final class Bar implements FooListener<ConcreteFoo> {
@Override
public void callback(final ConcreteFoo foo) {
// TODO Auto-generated method stub
}
}
static final class ConcreteFoo extends AbstractFoo<ConcreteFoo> {
protected ConcreteFoo(final Class<? extends FooListener<ConcreteFoo>> listenerClass) {
super(listenerClass);
}
@Override
protected ConcreteFoo getSelf() {
return this;
}
}
static abstract interface FooListener<FOO extends AbstractFoo<FOO>> {
void callback(FOO abstractFoo);
}
static abstract class AbstractFoo<SELF extends AbstractFoo<SELF>> {
private final Class<? extends FooListener<SELF>> listenerClass;
protected AbstractFoo(final Class<? extends FooListener<SELF>> listenerClass) {
this.listenerClass = listenerClass;
}
protected abstract SELF getSelf();
// Bar might implement FooListener, but I don't control it,
// so I have no guarantee
public void externalMethod(final Bar bar) {
if (listenerClass.isInstance(bar)) {
final FooListener<SELF> listener = listenerClass.cast(bar);
listener.callback(getSelf()); // compiles
}
}
}