Polimorfismo: ¿Por qué usar "List list = new ArrayList" en lugar de "ArrayList list = new ArrayList"? [duplicar]


Posible Duplicado:
¿Por qué debería preferirse la interfaz para una clase Java?

Cuándo debo usar

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

ArrayList hereda de List, así que si algunas características de ArrayList no están en List, entonces habré perdido algunas de las características de ArrayList, ¿verdad? ¿Y el compilador notará un error al intentar acceder a estos métodos?

Author: Community, 2012-03-24

8 answers

La razón principal por la que haría esto es para desacoplar su código de una implementación específica de la interfaz. Cuando escribes tu código así:

List list = new ArrayList();  

El resto de su código solo sabe que los datos son de tipo List, lo cual es preferible porque le permite cambiar entre diferentes implementaciones de la interfaz List con facilidad.

Por ejemplo, digamos que estabas escribiendo una biblioteca de 3rd party bastante grande, y digamos que decidiste implementar el núcleo de tu biblioteca con a LinkedList. Si su biblioteca depende en gran medida del acceso a los elementos de estas listas, entonces eventualmente encontrará que ha tomado una mala decisión de diseño; se dará cuenta de que debería haber utilizado un ArrayList (que da tiempo de acceso O(1)) en lugar de un LinkedList (que da tiempo de acceso O(n)). Suponiendo que haya estado programando en una interfaz, hacer tal cambio es fácil. Simplemente cambiarías la instancia de List de,

List list = new LinkedList();

A

List list = new ArrayList();  

Y sabes que esto funcionará porque ha escrito su código para seguir el contrato proporcionado por la interfaz List.

Por otro lado, si hubiera implementado el núcleo de su biblioteca usando LinkedList list = new LinkedList(), hacer tal cambio no sería tan fácil, ya que no hay garantía de que el resto de su código no haga uso de métodos específicos de la clase LinkedList.

Con Todo, la elección es simplemente una cuestión de diseño... pero este tipo de diseño es muy importante (especialmente cuando se trabaja en grandes proyectos), ya que le permiten realizar cambios específicos de la implementación más adelante sin romper el código existente.

 223
Author: Alex Lockwood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-21 21:22:15

Esto se llama programación a interfaz. Esto será útil en caso de que desee pasar a alguna otra implementación de la Lista en el futuro. Si desea algunos métodos en ArrayList entonces tendría que programar a la implementación que es ArrayList a = new ArrayList().

 63
Author: tsatiz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-21 22:30:19

Esto también es útil cuando se expone una interfaz pública. Si usted tiene un método como este,

public ArrayList getList();

Entonces usted decide cambiarlo a,

public LinkedList getList();

Cualquiera que estuviera haciendo ArrayList list = yourClass.getList() tendrá que cambiar su código. Por otro lado, si lo haces,

public List getList();

Cambiar la implementación no cambia nada para los usuarios de tu API.

 19
Author: Brendan Long,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-24 23:52:44

Creo que la respuesta de @tsatiz es mayormente correcta (programar una interfaz en lugar de una implementación). Sin embargo, al programar en la interfaz no perderá ninguna funcionalidad. Déjame explicarte.

Si declara su variable como una List<type> list = new ArrayList<type> en realidad no pierde ninguna funcionalidad de la lista de arraylos. Todo lo que necesitas hacer es lanzar tu list a un ArrayList. He aquí un ejemplo:

List<String> list = new ArrayList<String>();
((ArrayList<String>) list).ensureCapacity(19);

En última instancia, creo que tsatiz está en lo correcto, ya que una vez que lanzas a un ArrayList que ya no está codificando en una interfaz. Sin embargo, sigue siendo una buena práctica codificar inicialmente en una interfaz y, si luego se hace necesario, codificar en una implementación si es necesario.

¡Espero que eso ayude!

 10
Author: SecondSun24,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-27 18:52:58

Esto le permite escribir algo como:

void doSomething() {
    List<String>list = new ArrayList<String>();
    //do something
}

Más adelante, es posible que desee cambiarlo a:

void doSomething() {
    List<String>list = new LinkedList<String>();
    //do something
}

Sin tener que cambiar el resto del método.

Sin embargo, si desea utilizar un CopyOnWriteArrayList por ejemplo, tendría que declararlo como tal, y no como una Lista si desea utilizar sus métodos adicionales (addIfAbsent por ejemplo):

void doSomething() {
    CopyOnWriteArrayList<String>list = new CopyOnWriteArrayList<String>();
    //do something, for example:
    list.addIfAbsent("abc");
}
 7
Author: assylias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-28 08:15:34

Uso esa construcción siempre que no quiero agregar complejidad al problema. Es solo una lista, no hay necesidad de decir qué tipo de Lista es, ya que no importa el problema. A menudo uso la Colección para la mayoría de mis soluciones, ya que, al final, la mayoría de las veces, para el resto del software, lo que realmente importa es el contenido que contiene, y no quiero agregar nuevos objetos a la Colección.

Además, utilizas esa construcción cuando piensas que puedes querer cambiar la implementación de la lista que está utilizando. Digamos que estaba usando la construcción con un ArrayList, y su problema no era seguro hilo. Ahora, desea que sea seguro hilo, y para parte de su solución, se cambia a utilizar un vector, por ejemplo. En cuanto a los otros usos de esa lista no importará si es una AraryList o un Vector, solo una Lista, no se necesitarán nuevas modificaciones.

 5
Author: SHiRKiT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-24 15:31:35

Supongo que el núcleo de tu pregunta es por qué program to an interface, not to an implementation

Simplemente porque una interfaz le da más abstracción, y hace que el código más flexible y resistente a los cambios, porque puede utilizar diferentes implementaciones de la misma interfaz(en este caso, es posible que desee cambiar su Lista de la aplicación a una linkedList en lugar de un objeto ArrayList ) sin cambiar su cliente.

 4
Author: Mouna Cheikhna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-04 11:47:53

En general, desea programar contra una interfaz. Esto le permite intercambiar la implementación en cualquier momento. Esto es muy útil especialmente cuando se pasa una implementación que no conoces.

Sin embargo, hay ciertas situaciones en las que prefiere utilizar la implementación concreta. Por ejemplo, cuando se serializa en GWT.

 2
Author: stefan bachert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-24 16:07:51