これは、@RussellZahniser ソリューションが @assylias ソリューションよりも優れていると考える理由の長いバージョンです (ただし、別のひねりも追加します)。
ジェネリックを使用するときはいつでも、サブタイプまたはスーパータイプを許可するかどうかを検討してください。
最初はコンパイラが過度にペダンティックに見えるかもしれませんが、ジェネリクスには奇妙な逆の互換性があります。大まかに言うと、リンゴの袋は果物の袋ではありません. 果物の袋にはバナナを入れることができますが、りんごの袋には入れることができません。
したがって、ジェネリックを使用するときは常に、サブタイプ (消費用) またはスーパータイプ (生産用) を許可するかどうかを検討してください。
AdditionalProcessing
あなたがコンバーターであると仮定すると、実際にはAdditionalProcessing<IN, OUT>
.
では、AdditionalProcessing
互換性があるのはいつですか?
タイプのコンバーターが必要であると仮定しますAdditionalProcessing<Fruit, Fruit>
。あらゆる種類の果物を受け入れる必要がありますが、どの種類の果物を返すかは問題ではありません。つまり、リンゴをオレンジに変える可能性があります。ただし、リンゴを石に変換するものであってはなりません。そうすると、オレンジに餌を与えることができず、果物が得られないからです。
したがって、コンバーターの場合、map
関数は実際には次のようになります。
public <I, O> O map(I source, Class<O> destinationClass,
AdditionalProcessing<? super I, ? extends O> additionalProcessing)
以来:
? super I
: 「少なくとも果物を受け入れます (しかし、何か他のものも受け入れます!)」.
? extends O
: "ある種の果物を返します (ただし、リンゴだけかもしれません)".
果物の例は本当に価値があることがわかりました。
次にNoAdditionalProcessing
、次のようになります。
public class NoAdditionalProcessing<TYPE>
implements AdditionalProcessing<TYPE, TYPE> {
@Override
public void postProcess(Object o, Object o2) {
// Actually I would have expected something like "return o1;"
}
}
これは本質的に、最初の行でクレジットした 2 つの回答を融合したものです。ただし、あなたの質問から、あなたが望むかどうかを判断するのは困難super
ですextends
。そのため、両方が合理的であり、両方が必要な場合があることを強調したいと思います.
通常、これはsuper
入力タイプ(つまり、消費されたデータ) と出力タイプ (つまり、生成されたextends
タイプ)用になります。(ネストされたジェネリックではさらに厄介になります。)つまり、 a の場合、両方のスーパー タイプを受け入れるコンパレーターを許可する必要があります。ComapareTwoTypes<FIRST, SECOND>
パターンとしてのいくつかの例:
Validator<? super I, ? super O>
スーパータイプのみで検証を実行している場合は許容されます。比較のために両方の型を消費し、何も生成しません。
Converter<? super I, ? extends O>
スーパータイプを受け入れることを選択する場合があり、戻り値を特定のスーパータイプに制限する場合があります。最初のタイプを消費し、2 番目のタイプを生成します。
両方が である例を思いつくのははるかに困難ですextends
。Java コンパイラーは追加のヒントがないと確実に型を推測できないためです。これは、 コレクションの反変性のために、I
およびO
それ自体がジェネリック (別の型のコレクションなど) である場合に主に発生します。
ウィキペディアには、型の共分散と反分散に関する記事があり、ここで発生する状況に光を当てるのに役立つ可能性があります (残念ながら、この記事は少し理論的なものです)。しかし、コレクションは最も明白なケースです。この「リンゴの袋は果物の袋ではありません。バナナを入れることはできません」という例があったのはC++だったと思いますが、主なものは潜水艦を駐車場に置くことです(駐車場がある場合) -たくさんの車は一種の車の駐車場でしたが、そうではありません)。