¡Buena pregunta!
(En los siguientes comentarios, WRT una clase genérica en E
como Foo<E>
, defina "método covariante" como un método que devuelve una E
sin tener ningún parámetro usando E
, y un "método contravariant" como lo contrario: una que toma un parámetro formal del tipo E
pero no devuelve un tipo que implique E
. [La definición real de estos términos es más complicada, pero no importa que por ahora.])
Parece que el compilador intenta vincular T
a Object
en el caso de f1
, porque si lo hace
class Bar0 {
public static <T> void go(Foo< Foo< ? extends T > > f) {
// can pass a Foo<T> to a contravariant method of f;
// can use any result r of any covariant method of f,
// but can't pass T to any contravariant method of r
}
}
luego los go(f1)
obras, pero ahora go(f2)
no lo hace, porque a pesar de Foo<String> <: Foo< ? extends String >
, que no implica que Foo< Foo<String> > <: Foo< Foo< ? extends String > >
.
Estas son algunas modificaciones que compilan tanto para f1
y f2
:
class Bar1 {
public static <T> void go(Foo< ? super Foo<T> > f) {
// can't properly type the results of any covariant method of f,
// but we can pass a Foo<T> to any contravariant method of f
}
}
class Bar2 {
public static <T> void go(Foo< ? extends Foo< ? extends T > > f) {
// can't pass a Foo<T> to a contravariant method of f;
// can use result r of any covariant method of f;
// can't pass a T to a contravariant method of r;
// can use result of covariant method of r
}
}
Es genial ver ejemplos de trabajo. – Cyker
¿Qué tal el caso de 'Foo>'? Si necesito trabajar en términos de 'Foo >', puedo escribir 'Foo extiende Foo >> 'pero siento que traerá más varianza que en realidad me gustaría si pudiera usar' Foo > '. ¿Cómo se acepta la aceptación de 'Foo ' como 'Foo >' en términos de varianza? –
ony
Si entiendo tu pregunta @ony, no la acepto en absoluto. 'Foo>' no es un 'Foo < Foo< ? >>'.En general, 'G < S >' no es un 'G < T >' incluso si 'S' es una' T', pero 'G < S >' es una 'G extiende T> 'y' G < T > 'es un' G < ? super S > '. 'Foo < ? >' es la abreviatura de 'Foo Extiende Object> ', por lo que' Foo < String > 'es un' Foo < ? > '. Pero deje que 'Foo < String >' sea 'S' y' Foo < ? > 'be' T'. La falta de relación de arriba significa 'Foo < S >' no es un 'Foo < T >'. –