あなたが立てた仮定は、実際に立っているものとは反対です:
Iterable<? extends iface_classB> getThings();
は、少なくともの機能をgetThings()持つ反復可能なオブジェクトを返すことを意味します。したがって、オブジェクトが.iface_classBgetThings()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