So following the solution described in Java - Inherited Fluent method return type to return incident class' type, not parent's. I want to extend it to multiple levels.
The solution works in one level obviously. Here is compiled and runnable code (no dependencies):
public enum X {
;
static interface BaseFoo<T, S extends BaseFoo<T, S>> {
S foo();
}
static interface Foo<T> extends BaseFoo<T, Foo<T>> {
void foo1();
}
static abstract class AbstractFooBase<T, S extends BaseFoo<T, S>> implements BaseFoo<T, S> {
abstract void internalFoo();
@Override
public S foo() {
internalFoo();
return (S)this;
}
}
static class FooImpl<T> extends AbstractFooBase<T, Foo<T>> implements Foo<T> {
@Override
void internalFoo() {
System.out.println("inside FooImpl::internalFoo()");
}
@Override
public void foo1() {
System.out.println("inside FooImpl::foo1()");
}
}
public static void main(String[] args) {
Foo<String> foo = new FooImpl<String>();
foo.foo().foo1();
}
}
However things getting difficult when I add an new level in the object inheritance hierarchy. The code below won't compile:
public enum X {
;
static interface BaseFoo<T, S extends BaseFoo<T, S>> {
S foo();
}
static interface Foo<T> extends BaseFoo<T, Foo<T>> {
void foo1();
}
static interface BaseBar<T, S extends BaseBar<T, S>> extends BaseFoo<T, S> {
S bar();
}
static interface Bar<T> extends BaseBar<T, Bar<T>> {
void bar1();
}
static abstract class AbstractFooBase<T, S extends BaseFoo<T, S>> implements BaseFoo<T, S> {
abstract void internalFoo();
@Override
public S foo() {
internalFoo();
return (S)this;
}
}
static class FooImpl<T> extends AbstractFooBase<T, Foo<T>> implements Foo<T> {
@Override
void internalFoo() {
System.out.println("inside FooImpl::internalFoo()");
}
@Override
public void foo1() {
System.out.println("inside FooImpl::foo1()");
}
}
static abstract class AbstractBarBase<T, S extends BaseBar<T, S>> extends FooImpl<T> implements BaseBar<T, S> {
abstract void internalBar();
@Override
public S bar() {
internalBar();
return (S)this;
}
}
static class BarImpl<T> extends AbstractBarBase<T, Bar<T>> implements Bar<T> {
@Override
void internalBar() {
System.out.println("inside BarImpl::internalBar()");
}
@Override
public void bar1() {
System.out.println("inside BarImpl::bar1()");
}
}
public static void main(String[] args) {
Foo<String> foo = new FooImpl<String>();
foo.foo().foo1();
Bar<Boolean> bar = new BarImpl<Boolean>();
bar.foo().bar1();
}
}
The compile time error message is:
X.java:40: X.BaseFoo cannot be inherited with different arguments: <T,S> and <T,X.Foo<T>>
static abstract class AbstractBarBase<T, S extends BaseBar<T, S>> extends FooImpl<T> implements BaseBar<T, S> {
^
X.java:49: X.BaseFoo cannot be inherited with different arguments: <T,X.Bar<T>> and <T,X.Foo<T>>
static class BarImpl<T> extends AbstractBarBase<T, Bar<T>> implements Bar<T> {
^
Note: X.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors
Any idea how to work around it?