私はジェネリックスを利用するコードをいくつか開発しています。私の指針となる原則の1つは、今日だけでなく、将来のシナリオでも使用できるようにすることでした。ただし、いくつかの同僚は、拡張性のために読みやすさを犠牲にしている可能性があると述べています。これを解決するために考えられる方法についてフィードバックを集めたかったのです。
具体的には、ここに変換を定義するインターフェースがあります。まず、項目のソースコレクションから開始し、各要素に変換を適用して、結果を宛先コレクションに保存します。さらに、宛先のコレクションを呼び出し元に返すことができるようにしたいのですが、コレクションの参照を使用するように強制するのではなく、宛先のコレクションに実際に提供したコレクションの種類を使用できるようにしたいと思います。
最後に、宛先のコレクション内のアイテムのタイプが、ソースのコレクション内のアイテムのタイプと異なるようにすることができます。これは、おそらく変換が行うためです。たとえば、私のコードでは、変換後にいくつかのソース項目が1つの宛先項目を構成しています。
これにより、次のインターフェースが生成されます。
interface Transform<Src, Dst> {
<DstColl extends Collection<? super Dst>> DstColl transform(
Collection<? extends Src> sourceCollection,
DstColl destinationCollection);
}
インターフェースを適切にスーパータイプとサブタイプで使用できるようにするために、私はすべてがうまくいってJosh BlochのPECS原則(プロデューサー拡張、コンシューマースーパー)を適用しようとしました。最終結果は幾分怪物です。
さて、このインターフェースを拡張して、どういうわけかそれを特化できればいいのですが。たとえば、ソースアイテムのサブタイプとデスティネーションアイテムのスーパータイプをうまく使用する必要がない場合は、次のようにします。
interface SimpleTransform<Src, Dst> {
<DstColl extends Collection<Dst>> DstColl transform(
Collection<Src> sourceCollection,
DstColl destinationCollection);
}
しかし、Javaでそれを行う方法はありません。私はこのインターフェースの実装を、恐怖で走るのではなく、他の人が実際に行うことを検討するようなものにしたいと考えています。私はいくつかのオプションを検討しました:
- 宛先のコレクションを返さないでください。変換を実行しても何も返されないことを考えると、奇妙に思えます。
- このインターフェイスを実装する抽象クラスがありますが、パラメーターを使いやすいものに変換し、より単純なシグネチャを持つ別のメソッド "translateImpl()"を呼び出します。これにより、実装者の認識の負担が少なくなります。しかし、インターフェイスをユーザーフレンドリーにするためだけに抽象クラスを作成しなければならないのは奇妙です。
- 拡張性を忘れ、よりシンプルなインターフェースを備えています。おそらく、それを宛先のコレクションを返さないことと組み合わせます。しかし、それは将来の私の選択肢を制限します。
どう思いますか?使用できるアプローチがありませんか?
Collection<? extends Src> srcCollection
使用する必要がありますIterable<? extends Src>