私が使用しているサードパーティのライブラリには、次のような階層があります。
public abstract class Foo
{
// Class is public in the Java sense and public in the library's API
}
public class FooImpl extends Foo
{
// While this class is public in the Java sense, it is
// NOT part of the public API and is not even documented
// Library functions that hand back instances of this class
// hand them back as type Foo
}
ライブラリ内のさまざまなメソッドは、 type のものを操作しFoo
ます。ドキュメントによると、Foo
ユーザーは拡張Foo
して具体的な実装を作成でき、(明らかに) ライブラリは具体的な実装を提供します。
ライブラリ提供の実装には満足していますが、その動作を少し変更したいメソッドが 1 つあります。しかし、私が与えられたヒエラルキーは私をつまずかせています。
インターフェイスだった場合 Foo
(そうではありません!)、私はこれを行うだけです:
public FooWrapper implements Foo
{
private Foo wrappedImpl;
public FooWrapper(Foo toBeWrapped) {
wrappedImpl = toBeWrapped;
}
List<Whatever> methodIWantToTweak() {
List<Whatever> list = wrappedImpl.methodIWantToTweak();
do_something_to_list(list);
return list;
}
Something methodThatsOk() {
return wrappedImpl.methodThatsOk();
}
// similar delegations for remaining methods
}
しかし、それはインターフェースではないので、これを行うことはできません。少なくとも、きれいに行うことはできません。
私が考えられる唯一のことは次のとおりです。
1) API 非公開クラス FooImpl を拡張し、微調整したいメソッドをオーバーライドします。
2) 次のようにします。
public class FooWrapper extends Foo
{
private Foo wrappedImpl;
public FooWrapper(Foo toBeWrapped) {
super();
wrappedImpl = toBeWrapped;
}
List<Whatever> methodIWantToTweak() {
List<Whatever> list = wrappedImpl.methodIWantToTweak();
do_something_to_list(list);
return list;
}
Something methodThatsOk() {
return wrappedImpl.methodThatsOk();
}
// Override all non-final public, protected, and package-local
// methods and delegate them to wrappedImpl
}
これらのアプローチは両方とも、私には臭いがします。最初のものには、それが知っているはずのないクラスに依存し、ライブラリの将来のバージョンで変更/消失/名前が変更される可能性があるという問題があります。2 つ目は、 のスーパークラス部分がFooWrapper
実際には使用されず、 の最終メソッドまたはプライベート メソッドをオーバーライドできないというFoo
問題があります (これらの場合、 にデリゲートできないため、問題が発生しますwrappedImpl
)。
少なくとも正しい動作が得られるため、最初のアプローチを使用する必要があると思いますが、2番目のアプローチは、Foo
.
では、私は運が悪いのでしょうか?私が見落としている他のアプローチ/アイデアは何ですか?