2012-01-23 12 views
16

He leído en varios lugares, incluido here, que tener un comodín delimitado en un método de devolución es una mala idea. Sin embargo, no puedo encontrar una manera de evitarlo con mi clase. ¿Me estoy perdiendo de algo?Comodín limitado a Java en el tipo de retorno

La situación es como la siguiente:

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 yo quiero ser capaz de consumir cualquier publicación que se encuentra en alguna variante de Inglés. La clase necesita permitir el acceso a la publicación desde el exterior, pero, idealmente, los llamadores de getPublication no desearían el resultado como un comodín delimitado. Estarían felices con Publication<English>.

¿Hay alguna manera de evitar esto?

+0

El artículo 28 en "Java eficaz" de Joshua Bloch recomienda: "No use tipos de comodines como tipos de devolución". –

Respuesta

12

Los comodines delimitados son contagiosos, que es a lo que la página que enlazas parece lamentarse. Bueno, no se puede negar eso ... pero supongo que no lo veo como un gran problema.

Hay muchos casos en los que devuelvo un comodín delimitado exactamente porque es contagioso. El JDK, para bien o para mal (lo digo peor, pero esa es una caja de jabón diferente :)) no tiene interfaces para colecciones de solo lectura. Si devuelvo un List<Foo> que no deseo que la gente modifique (tal vez incluso esté incluido con seguridad en Collections.unmodifiableList), no hay forma de declararlo en mi firma de devolución. Como una solución alternativa para un pobre, a menudo devolveré List<? extends Foo>. Todavía es posible tratar de modificar esa lista eliminando elementos o insertando null, pero al menos el hecho de que no se puede add(new Foo()) sirve como un recordatorio de que esta lista es probablemente de solo lectura.

De manera más general, creo que devolver algo con un tipo de devolución limitada es perfectamente razonable si realmente desea que el sitio de llamada tenga acceso restringido al objeto.

Otro ejemplo sería una cola segura para subprocesos que transfiere a diferentes subprocesos, donde un subproceso es un productor y el otro es un consumidor. Si le da al productor un Queue<? super Foo>, está claro que tiene la intención de poner artículos en él (y no sacar los artículos). Del mismo modo, si le da al consumidor un Queue<? extends Foo>, está claro que tiene la intención de retirar los artículos (y no poner los artículos).

4

¿Se puede utilizar un parámetro de tipo delimitado en la declaración de clase?

class EnglishReaderOfPublications<E extends English> { ... 

Luego puede usar este parámetro de tipo dondequiera que tenga el parámetro comodín.

+1

Podría pero no estoy seguro si ayuda en mi caso.Tengo una colección heterogénea de estos lectores en inglés y quiero obtener las publicaciones de ellos cuando lo único que me importa es que sean 'Publicación '. Supongo que mi pregunta es más acerca de por qué 'Publicación ' no es lo mismo que 'Publicación '. Entiendo por qué esto es para colecciones (puede agregar algo que satisfaga el comodín pero violó el tipo real) pero, como Publication no ofrece ninguna forma de cambiar el idioma en tiempo de ejecución, realmente no estoy * sintiendo * por qué esto sería incorrecto. – thehouse

0

"idealmente, los llamadores de getPublication no querrían el resultado como un comodín delimitado. Estarían contentos con Publication<English>."

¿Por qué "would not" lo quieren? ¿Estarían "contentos" con Publication<? extends English>? La pregunta es realmente lo que estas personas deben hacer con este objeto de Publicación. Si todo lo que hacen es sacar cosas de él, entonces Publication<? extends English> es suficiente, y es mejor porque es más general. Sin embargo, si necesitan poner cosas en él, entonces no puede usar Publication<? extends English>.

+0

Básicamente debido a la contaminación. El código de llamada obtiene cada publicación llamando 'getPublication' y la coloca en' Set'. Por el momento, tengo que pasar 'Set > 'que hace que mi código sea difícil de leer. Quizás estoy siendo quisquilloso. – thehouse

+0

Más difícil de leer, pero más general de usar. Estoy de acuerdo en que la sintaxis es lamentablemente detallada. Si estas clases/métodos están solo en su propio código, puede elegir el enfoque fácil de leer si lo prefiere. Si está escribiendo una API que espera que otros lean, es muy importante tener los comodines correctos, porque sería una pena que alguien tuviera una Publicación y no podría usarlo en su API debido a tipeo "perezoso" (o "bonito" si lo desea). – yshavit

Cuestiones relacionadas