あなたが立てた仮定は、実際に立っているものとは反対です:
Iterable<? extends iface_classB> getThings();
は、少なくともの機能をgetThings()
持つ反復可能なオブジェクトを返すことを意味します。したがって、オブジェクトが.iface_classB
getThings()
Iterable< impl_of_iface_classB >
iface_classB
たとえば、によって返されるオブジェクトがgetThings()
実際に であるIterable<impl2_of_iface_classB>
場合impl2_of_iface_classB
はどうなるiface_classB
でしょうか。反復可能なオブジェクトには、オブジェクトの機能がありませんimpl_of_iface_classB
。
実際には、B1
とB2
が から派生している場合、B
完全に許容されます。
A<? extends B> x;
A<B1> y;
A<B2> z;
x = y;
x = z;
したがってgetThings()
、ジェネリック パラメータが何を表しているかという点で信頼することはできません。「プレーン」としてのみ使用できますiface_classB
。
さらに言えば、 に代入できることを期待しますが、Iterable<iface_classB>
できません (チェックされていないキャストを実行しない限り、そうではありません)。これは、ワイルドカード記号が本質的に「実行可能な汎用パラメーターのセット」を意味するためです。ワイルドカードを、使用する具体的なジェネリック パラメーターに置き換えると想像してください。パラメーターが一致しない場合、互換性のない型が原因で、通常のコンパイル時エラーが発生します。コンパイラは、すべてのケースを考慮する必要があるため、それを行うことはできません。したがって、
A<? extends B> x;
A<B> y = x;
は事実上安全ですが、 とはx
異なるパラメーターが割り当てられる可能性がB
あり、割り当ての両側で異なる型が生成される可能性があるため、許可されません。それどころか、
A<B> x;
A<? extends B> y = x;
のタイプが代替y
のセットを表し、そのセットに が含まれているため、 が許可されます。上記のように が割り当てられるとすぐに、セットの具体的な評価が実際に選択されます。A<B>
y