2009-09-27 19 views
17

Esta es una verdadera pregunta para principiantes (todavía estoy aprendiendo los conceptos básicos de Java).¿Por qué se declaran las variables con su nombre de interfaz en Java?

puedo (tipo de) entender por qué los métodos obtendrá una lista <cadena> en lugar de una Cadena de ArrayList < >, o por qué aceptarían un parámetro de lista en lugar de un ArrayList. Si no hace ninguna diferencia en el método (es decir, si no se requieren métodos especiales de ArrayList), esto haría que el método sea más flexible y más fácil de usar para las personas que llaman. Lo mismo ocurre con otros tipos de colecciones, como Establecer o Mapa.

Lo que no entienden: que parece ser una práctica común para crear variables locales como esto:

List<String> list = new ArrayList<String>(); 

Si bien esta forma es menos frecuente:

ArrayList<String> list = new ArrayList<String>(); 

¿Cuál es la ventaja aquí?

Todo lo que puedo ver es una desventaja menor: se debe agregar una línea de "importación" separada para java.util.List. Técnicamente, se puede usar "import java.util. *", Pero tampoco lo veo con mucha frecuencia, probablemente porque algunas IDE agregan automáticamente las líneas de "importación".

Respuesta

20

Al leer

List<String> list = new ArrayList<String>(); 

usted consigue la idea de que todo lo que importa es ser un List<String> y poner menos énfasis en la implementación real. Además, se restringe a los miembros declarados por List<String> y no a la implementación particular. No importa si sus datos se almacenan en una matriz lineal o en una estructura de datos sofisticada, siempre que se vea como List<String>.

Por otro lado, leer la segunda línea le da la idea de que el código le importa sobre la variable que es ArrayList<String>. Al escribir esto, está diciendo implícitamente (a los lectores futuros) que no debe cambiar ciegamente el tipo de objeto real porque el resto del código depende del hecho de que realmente es un ArrayList<String>.

+5

Esto es la invenciónphilia. Las eficiencias de una implementación frente a otra dependen del código que usa la variable: no puedo ver que alguna vez desearía algo más que un estrecho acoplamiento entre las dos. –

+0

"No puedo ver si alguna vez querría algo más que un estrecho acoplamiento entre los dos": ¿no está todo el concepto de interfaces basado en el hecho de que en realidad ** quieres ** un acoplamiento flojo? –

+1

Por supuesto.Pero, ¿cuándo querría un acoplamiento flexible entre el trabajo de una función y sus variables locales? Especialmente cuando se selecciona una implementación de colección, ya que las colecciones a menudo se optimizan para situaciones específicas. –

1

si después desea cambiar la implementación de la lista y utilizar, por ejemplo, LinkedList (quizás para un mejor rendimiento), no tiene que cambiar todo el código (y API si es su biblioteca). si el orden no importa, debe devolver la Colección para poder cambiarla fácilmente a Establecer si necesita elementos para ordenar.

+0

"por qué los métodos devolverían una lista en lugar de una lista de arreglos " <- entonces su API;) – IAdapter

1

La mejor explicación que puedo encontrar (porque no programo en Java con tanta frecuencia como en otros idiomas) es que hace que sea más fácil cambiar el tipo de lista de "back-end" manteniendo el mismo código/interfaz en la que todo lo demás confía. Si primero lo declaras como un tipo más específico, luego decides que quieres un tipo diferente ... si algo sucede con el uso de un método específico de ArrayList, eso es trabajo extra.

Por supuesto, si realmente necesita comportamiento específico de ArrayList, debería ir con el tipo de variable específico en su lugar.

7

El uso de la interfaz le permite cambiar rápidamente la implementación subyacente de List/Map/Set/etc.

No se trata de guardar las pulsaciones de teclas, se trata de cambiar la implementación rápidamente.Idealmente, no debería exponer los métodos específicos subyacentes de la implementación y simplemente usar la interfaz requerida.

2

Sugeriría pensar en esto desde el otro extremo. Por lo general, quiere una Lista o un Conjunto o cualquier otro tipo de Colección, y realmente no le importa cómo se implementa esto en su código. Por lo tanto, su código solo funciona con una lista y hacer lo que sea necesario (también redactado como "siempre codifica las interfaces").

Cuando crea la lista, debe decidir qué implementación real desea. Para la mayoría de los propósitos, ArrayList es "lo suficientemente bueno", pero a su código realmente no le importa. Al apegarse al uso de la interfaz, usted transmite esto al futuro lector.

Por ejemplo, tengo la costumbre de tener código de depuración en mi método principal, que vuelca las propiedades del sistema a System.out - por lo general, es mucho mejor ordenarlas. La forma más fácil es simplemente dejar "Map map = new TreeMap (properties);" y luego iterar a través de ellos, ya que TreeMap devuelve las claves ordenadas.

Cuando aprenda más sobre Java, también verá que las interfaces son muy útiles en pruebas y burlas, ya que puede crear objetos con un comportamiento especificado en tiempo de ejecución que se ajuste a una interfaz determinada. Un ejemplo avanzado (pero simple) se puede ver en http://www.exampledepot.com/egs/java.lang.reflect/ProxyClass.html

-2

Básicamente esto proviene de personas que tienen que ejecutar proyectos grandes, posiblemente por otros motivos: lo escuchas todo el tiempo. Por qué, en realidad no sé. Si necesita una lista de matriz, o Hash Map o Hash Set o cualquier otra cosa, no veo el sentido de eliminar los métodos al convertirlos a una interfaz.

Digamos, por ejemplo, recientemente aprendí a usar e implementar HashSet como una estructura de datos de principio. Supongamos, por alguna razón, que fui a trabajar en un equipo. ¿No necesitaría esa persona saber que los datos estaban basados ​​en enfoques hash en lugar de estar ordenados por alguna base? El enfoque de back-end observado por Twisol funciona en C/C++, donde puedes exponer los encabezados y vender una biblioteca. Si alguien sabe cómo hacerlo en Java, me imagino que usaría JNI, y en ese momento me parece más sencillo. para usar C/C++ donde puede exponer los encabezados y compilar libs utilizando las herramientas establecidas para ese fin.

En el momento en que puede obtener alguien que pueda instalar un archivo jar en el directorio de extensiones, me parece que la entidad podría estar a solo unos pasos de distancia. Dejé varias bibliotecas de cifrado en el directorio de extensiones, que era útil, pero Realmente me gustaría ver una base clara y concisa dilucidada. Me imagino que lo hacen todo el tiempo.

En este punto, me parece que es una ofuscación clásica, pero tenga cuidado: tiene que programar algo antes de que el problema sea importante.

+0

Me perdiste por completo hacia el final. – user183037

+2

y yo. Pareces haber perdido el punto de las interfaces. Además, no hay casting aquí. – DNA

0

El objetivo es identificar el comportamiento que desea/necesita y luego usar la interfaz que proporciona ese comportamiento. El es el tipo para tu variable. Luego, use la implementación que satisfaga sus otras necesidades: eficiencia, etc. Esto es lo que crea con "nuevo". Esta dualidad es una de las principales ideas detrás de OOD. El problema no es particularmente significativo cuando se trata de variables locales, pero rara vez duele seguir buenas prácticas de codificación todo el tiempo.

Cuestiones relacionadas