2010-05-26 15 views
31

Tengo un objeto que almacena algunos datos en una lista. La implementación podría cambiar más adelante y no quiero exponer la implementación interna al usuario final. Sin embargo, el usuario debe tener la capacidad de modificar y acceder a esta colección de datos. En este momento tengo algo como esto:¿Es mejor usar Lista o Colección?

public List<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(List<SomeDataType> data) { 
    this.data = data; 
} 

¿Quiere decir esto que he permitido que los detalles de implementación interna se escapen? ¿Debo hacer esto en su lugar?

public Collection<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(Collection<SomeDataType> data) { 
    this.data = new ArrayList<SomeDataType>(data); 
} 
+9

Una cosa a tener en cuenta es que si devuelve la colección o lista actual, está permitiendo que otra persona haga lo que quiera, incluso eliminar elementos o incluso borrar todo. Puede ser mejor devolver un contenedor no mutable o una copia de la lista. –

+1

@PaulTomblin cierto, pero es un poco excesivo y artificial para el sistema. Los envoltorios no modificables tienen sentido cuando se trabaja con objetos administrados por middleware de persistencia, y aun así solo en casos raros. – comeGetSome

+0

@comeGetSome, es por eso que dije "puede" en lugar de "debo". Dependería del caso de uso: si estuviera haciendo una API para que otros la usen, devolvería una copia o un contenedor. Si fuera para mí o para colegas de confianza, colocaría un gran "NO MODIFICAR ESTE VALOR" en los javadocs y lo dejaría así. –

Respuesta

24

Simplemente depende, ¿desea que sus usuarios puedan indexar en los datos? Si es así, use List. Ambas son interfaces, por lo que no está filtrando detalles de implementación, realmente, solo necesita decidir la funcionalidad mínima necesaria.

0

Si me preocupaba ocultar la representación interna de mis datos a un usuario externo, usaría XML o JSON. De cualquier manera, son bastante universales.

+0

¿eso significa siempre el tipo de retorno de cadena? – erdogany

+0

Por supuesto. XML y JSON están destinados a ser bastante universales, ¿y qué podría ser más universal que una cadena? – Cyberherbalist

+2

Bueno, si estoy pasando datos entre aplicaciones, voy a utilizar una codificación de ese tipo. Pero si estoy hablando de un valor de retorno de una función ... conviértalo a XML, devuélvalo como una Cadena, y luego la persona que llama tiene que analizar el XML. Es una gran cantidad de complejidad y sobrecarga sólo para devolver una matriz. – Jay

1

Sí, su primera alternativa no incluye los detalles de implementación si no forma parte de su contrato de interfaz que el método siempre devuelva una lista. Además, permitir que el código de usuario reemplace su instancia de colección es algo peligroso, porque la implementación que pasan puede no comportarse como espera.

Por supuesto, todo es cuestión de cuánto confías en tus usuarios. Si tomas la filosofía de Python de que "todos consentimos adultos aquí", entonces el primer método está bien. Si crees que tu biblioteca será utilizada por desarrolladores sin experiencia y necesitas hacer todo lo posible para "cuidarlos" y asegurarte de que no hagan algo mal, entonces es preferible no dejarlos configurar la colección y ni siquiera regresar. la colección real En su lugar, devuelva una copia (superficial) de la misma.

+1

java.util.Collections contiene métodos estáticos como unmodifiableList() que simplemente envuelve colecciones de modo que todos los métodos que modificarían la colección devuelvan errores. Como la creación de instancias de los contenedores es una operación de tiempo constante, es preferible incluso una copia poco profunda (qué código de cliente puede crearse si necesita una colección mutable). –

0

Depende de qué garantías desee proporcionar al usuario. Si los datos son secuenciales de modo que el orden de los elementos sea importante y permita duplicados, utilice una lista. Si el orden de los elementos no es importante y los duplicados pueden o no estar permitidos, entonces use una colección. Como en realidad está devolviendo la colección subyacente, no debe tener una función de obtención y establecimiento, solo una función de obtención, ya que la colección devuelta puede estar mutada. Además, proporcionar una función de conjunto permite que el usuario cambie el tipo de colección, mientras que usted probablemente desee que el tipo particular sea controlado por usted.

5

Usar el tipo más general, que es Colección, tiene más sentido a menos que haya alguna razón explícita para usar el tipo más específico - Lista. Pero haga lo que haga, si se trata de una API para el consumo público, tenga en cuenta en la documentación lo que hace; si devuelve una copia superficial de la colección, dígalo.

7

Al devolver una implementación de una interfaz o clase que está en una jerarquía alta, la regla general es que el tipo de declaración declarada debe ser el nivel MÁS ALTO que proporciona la funcionalidad mínima que está dispuesto a garantizar a la persona que llama, y que la persona que llama razonablemente necesita. Por ejemplo, supongamos que lo que realmente devuelve es una ArrayList. ArrayList implementa List and Collection (entre otras cosas). Si espera que la persona que llama necesite usar la función get (int x), no funcionará devolver una Colección, necesitará devolver una Lista o ArrayList. Siempre que no vea ninguna razón por la cual alguna vez podría cambiar su implementación para usar algo que no sea una lista, digamos un conjunto, entonces la respuesta correcta es devolver una lista. No estoy seguro de si hay alguna función en ArrayList que no esté en la Lista, pero si la hay, se aplicará el mismo razonamiento. Por otro lado, una vez que devuelve una Lista en lugar de una Colección, ahora ha bloqueado su implementación hasta cierto punto. Mientras menos pongas en tu API, menos restricciones pondrás en futuras mejoras.

(En la práctica, casi siempre devolverá una lista de este tipo de situaciones, y nunca me ha quemado. Pero probablemente realmente debería devolver una colección.)

9

independiente de la capacidad de índice en la lista a través de la lista .get (int), ¿los usuarios (o usted) tienen la expectativa de que los elementos de la colección se encuentran en un orden confiable y predecible? ¿Puede la colección tener múltiplos del mismo artículo? Ambas son expectativas de listas que no son comunes en colecciones más generales. Estas son las pruebas que uso al determinar qué abstracción exponer al usuario final.

14

La vuelta de una lista está en línea con la programación a la interfaz más adecuada.

La devolución de una colección causaría ambigüedad al usuario, ya que una colección devuelta podría ser: Establecer, Lista o Cola.

Cuestiones relacionadas