То, что вы пытаетесь сделать, это эмулировать тип SELF в Java с использованием обобщений. См. эту ссылку или другой сайт , чтобы узнать, как это сделать. Тем не менее, нет способа принудительно установить, что 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);
}
}
Вместо того, чтобы идти по этому пути, я бы сначала подумал о выборе дизайна, который привел вас сюда:
Возможно, меньшее количество параметров типа на самом деле является решением, полагаясь только на интерфейсы.
РЕДАКТИРОВАТЬ: одним из возможных решений, если вы не хотите приводить (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
}
}
}