Polimorfismo: ¿Por qué usar “List list = new ArrayList” en lugar de “ArrayList list = new ArrayList”?

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

Cuando debería usar

List list = new ArrayList(); 

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

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

 List list = new ArrayList(); 

el rest de su código solo sabe que los datos son de tipo List , lo cual es preferible porque le permite alternar entre diferentes implementaciones de la interfaz List fácilmente.

Por ejemplo, supongamos que está escribiendo una biblioteca bastante grande de terceros, y diga que decidió implementar el núcleo de su biblioteca con LinkedList . Si su biblioteca depende en gran medida del acceso a los elementos en estas listas, eventualmente descubrirá que ha tomado una mala decisión de diseño; se dará cuenta de que debería haber usado una ArrayList (que da O (1) tiempo de acceso) en lugar de una LinkedList (que otorga O (n) el tiempo de acceso). Suponiendo que haya estado progtwigndo en una interfaz, hacer ese cambio es fácil. Simplemente cambiaría la instancia de List from,

 List list = new LinkedList(); 

a

 List list = new ArrayList(); 

y usted sabe que esto funcionará porque ha escrito su código para seguir el contrato provisto por la interfaz de la List .

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

En general, 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 proyectos grandes), ya que le permitirá realizar cambios específicos de la implementación más tarde sin romper el código existente.

Esto se llama progtwigción para la interfaz. Esto será útil en caso de que desee pasar a alguna otra implementación de List en el futuro. Si quiere algunos métodos en ArrayList entonces debería progtwigr a la implementación que es ArrayList a = new ArrayList() .

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

 public ArrayList getList(); 

Luego decides cambiarlo a,

 public LinkedList getList(); 

Cualquiera que esté 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 su API.

Creo que la respuesta de @ tsatiz es en su mayoría correcta (progtwigción en una interfaz en lugar de una implementación). Sin embargo, al progtwigr en la interfaz, no perderá ninguna funcionalidad . Dejame explicar.

Si declara su variable como List list = new ArrayList , en realidad no pierde ninguna funcionalidad de ArrayList. Todo lo que necesita hacer es enviar su list a ArrayList . Aquí hay un ejemplo:

 List list = new ArrayList(); ((ArrayList) list).ensureCapacity(19); 

En definitiva, creo que tsatiz es correcto, ya que una vez que seleccionas ArrayList, ya no estás codificando en una interfaz. Sin embargo, sigue siendo una buena práctica codificar inicialmente en una interfaz y, si luego es necesario, codificar una implementación si es necesario.

¡Espero que ayude!

Esto te permite escribir algo como:

 void doSomething() { Listlist = new ArrayList(); //do something } 

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

 void doSomething() { Listlist = new LinkedList(); //do something } 

sin tener que cambiar el rest del método.

Sin embargo, si desea utilizar un CopyOnWriteArrayList por ejemplo, deberá declararlo como tal, y no como una lista si desea utilizar sus métodos adicionales (addIfAbsent por ejemplo):

 void doSomething() { CopyOnWriteArrayListlist = new CopyOnWriteArrayList(); //do something, for example: list.addIfAbsent("abc"); } 

Uso esa construcción cada vez que no quiero agregar complejidad al problema. Es solo una lista, no es necesario decir qué tipo de lista es, ya que no tiene importancia para el problema. A menudo utilizo Collection para la mayoría de mis soluciones, ya que, al final, la mayoría de las veces, para el rest del software, lo que realmente importa es el contenido que contiene, y no quiero agregar nuevos objetos a la Colección. .

Además, utiliza esa construcción cuando piensa que puede querer cambiar la implementación de la lista que está utilizando. Digamos que estaba usando la construcción con una ArrayList, y su problema no era seguro para subprocesos. Ahora, desea que sea seguro para subprocesos, y para parte de su solución, cambie para usar 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.

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

Simplemente porque una interfaz le brinda más abstracción y hace que el código sea más flexible y resistente a los cambios, porque puede usar diferentes implementaciones de la misma interfaz (en este caso, puede querer cambiar su implementación de lista a una lista enlazada en lugar de una ArrayList) sin cambiar su cliente

En general, desea progtwigr en una interfaz. Esto le permite intercambiar la implementación en cualquier momento. Esto es muy útil especialmente cuando te pasan una implementación que no sabes.

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

    Intereting Posts