lower - java type erasure
ComodÃn acotado de Java en el tipo de retorno (3)
He leído en varios lugares, incluido here que es una mala idea tener un carácter comodín acotado en un tipo de retorno de método. Sin embargo, no puedo encontrar una manera de evitarlo con mi clase. ¿Me estoy perdiendo de algo?
La situación se ve algo como esto:
class EnglishReaderOfPublications {
private final Publication<? extends English> publication;
EnglishReaderOfPublications(Publication<? extends English> publication) {
this.publication = publication;
}
void readPublication() {
publication.omNomNom();
}
Publication<? extends English> getPublication() {
return publication;
}
}
En resumen, una clase que quiero poder consumir cualquier publicación que esté en alguna variante al inglés. La clase debe permitir el acceso a la publicación desde el exterior, pero, idealmente, las personas que llaman getPublication
no querrían el resultado como un comodín acotado. Estarían felices con la Publication<English>
.
¿Hay alguna forma de evitar esto?
"idealmente, las personas que llaman getPublication no querrían el resultado como un comodín acotado. Estarían contentos con la Publication<English>
".
¿Por qué "no" lo quieren? ¿Estarían "felices" con la Publication<? extends English>
Publication<? extends English>
? La pregunta es realmente qué deben hacer estas personas que llaman con este objeto de publicación. Si todo lo que hacen es sacar cosas de esto, entonces ¿ Publication<? extends English>
Publication<? extends English>
es suficiente, y es mejor porque es más general. Sin embargo, si necesitan poner cosas en él, entonces no puedes usar la Publication<? extends English>
Publication<? extends English>
.
¿Se puede usar un parámetro de tipo acotado en la declaración de clase?
class EnglishReaderOfPublications<E extends English> { ...
Luego puede usar este parámetro de tipo en cualquier lugar donde tenga el parámetro de comodín.
Los comodines acotados son contagiosos, que es lo que parece lamentar la página a la que te vinculas. Bueno, no se puede negar eso ... pero creo que no lo veo como un problema tan grande.
Hay muchos casos en los que devuelvo un comodín acotado exactamente porque es contagioso. El JDK, para bien o para mal (lo digo para peor, pero esa es una caja de jabón diferente :)) no tiene interfaces para colecciones de solo lectura. Si devuelvo una List<Foo>
que no deseo que se modifique la gente (tal vez incluso esté incluida de forma segura en Collections.unmodifiableList
), no hay forma de declararlo en mi firma de devolución. Como solución alternativa de un hombre pobre, a menudo devolveré la List<? extends Foo>
List<? extends Foo>
. Aún es posible intentar modificar esa lista eliminando elementos o insertando un null
, pero al menos el hecho de que no pueda add(new Foo())
sirve como un recordatorio de que esta lista es probablemente de solo lectura.
Más en general, creo que devolver algo con un tipo de retorno acotado es perfectamente razonable si realmente desea que el sitio de llamadas tenga acceso restringido al objeto.
Otro ejemplo sería una cola segura para subprocesos que se entrega a diferentes subprocesos, donde un subproceso es un productor y el otro es un consumidor. Si le das al productor una Queue<? super Foo>
Queue<? super Foo>
, está claro que pretendes que pongan artículos en él (y no los saquen). Del mismo modo, si le das al consumidor una Queue<? extends Foo>
Queue<? extends Foo>
, está claro que pretende que saquen los elementos (y no los pongan).