そのため、Java 継承の Fluent メソッドの戻り値の型で説明されている解決策に従って、親の型ではなく、インシデント クラスの型を返します。複数のレベルに拡張したい。
ソリューションは明らかに 1 つのレベルで機能します。コンパイル済みで実行可能なコード (依存関係なし) は次のとおりです。
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();
}
}
ただし、オブジェクトの継承階層に新しいレベルを追加すると、事態が難しくなります。以下のコードはコンパイルされません。
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();
}
}
コンパイル時のエラー メッセージは次のとおりです。
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
それを回避する方法はありますか?