Polimorfismo: ¿Por qué utilizar "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
, por lo 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?
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 de esta manera:
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 List
interfaz con facilidad.
Por ejemplo, digamos que estaba escribiendo una biblioteca de terceros bastante grande y que decidió implementar el núcleo de su biblioteca con un archivo LinkedList
. Si su biblioteca depende en gran medida del acceso a elementos de estas listas, eventualmente descubrirá que ha tomado una mala decisión de diseño; Te darás cuenta de que deberías haber usado un ArrayList
(que proporciona un tiempo de acceso O(1)) en lugar de un LinkedList
(que proporciona un tiempo de acceso O(n)). Suponiendo que haya estado programando en una interfaz, realizar dicho cambio es fácil. Simplemente cambiarías la instancia de List
from,
List list = new LinkedList();
a
List list = new ArrayList();
y sabes que esto funcionará porque has escrito tu código para seguir el contrato proporcionado por la List
interfaz.
Por otro lado, si hubiera implementado el núcleo de su biblioteca usando LinkedList list = new LinkedList()
, realizar dicho cambio no sería tan fácil, ya que no hay garantía de que el resto de su código no utilice métodos específicos de la LinkedList
clase.
Considerándolo 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 proyectos grandes), ya que le permitirá realizar cambios específicos de la implementación más adelante sin romper el código existente.
Esto se llama programación para interfaz. Esto será útil en caso de que desee pasar a alguna otra implementación de List en el futuro. Si desea incluir algunos métodos, ArrayList
deberá programar la implementación ArrayList a = new ArrayList()
.
Esto también resulta útil al exponer una interfaz pública. Si tienes un método como este,
public ArrayList getList();
Entonces decides cambiarlo a,
public LinkedList getList();
Cualquiera que lo estuviera haciendo ArrayList list = yourClass.getList()
deberá 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 mayoritariamente correcta (programación en una interfaz en lugar de una implementación). Sin embargo, al programar la interfaz no perderá ninguna funcionalidad . Dejame explicar.
Si declara su variable como,
en realidad no pierde ninguna funcionalidad de ArrayList. Todo lo que necesitas hacer es bajar tu List<type> list = new ArrayList<type>
list
nivel a ArrayList
. He aquí un ejemplo:
List<String> list = new ArrayList<String>();
((ArrayList<String>) list).ensureCapacity(19);
En última instancia, creo que tsatiz tiene razón, ya que una vez que envías a 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 en una implementación si es necesario.
¡Espero que ayude!