una resueltos que polimorfismo metodo interfaz interfaces ejercicios ejemplos ejemplo clases clase abstractas abstracta java interface java-8 abstract-class default-method

resueltos - polimorfismo java



Interfaz con métodos predeterminados vs clase abstracta en Java 8 (13)

¿Cuándo debería usarse la interfaz con los métodos predeterminados y cuándo debería usarse una clase abstracta?

Compatibilidad con versiones anteriores: imagine que su interfaz está implementada por cientos de clases, modificar esa interfaz obligará a todos los usuarios a implementar el nuevo método agregado, aunque podría no ser esencial para muchas otras clases que implementan su interfaz. Además, permite su interfaz ser una interfaz funcional

Hechos y restricciones:

1-Solo se puede declarar dentro de una interfaz y no dentro de una clase o clase abstracta.

2-Debe proporcionar un cuerpo

3-No se supone que sea abstracto como otros métodos normales utilizados en una interfaz.

Como Java 8 permite la implementación predeterminada de métodos en la interfaz llamada Métodos predeterminados , parece haber una confusión entre cuándo utilizaría una abstract class .

Entonces, ¿cuándo debería usarse la interfaz con los métodos predeterminados y cuándo debería usarse una clase abstracta? ¿Las clases abstractas siguen siendo útiles en ese escenario?


Cada vez que tenemos una opción entre la clase abstracta y la interfaz, siempre debemos (casi) preferir los métodos predeterminados (también conocidos como defensor o extensiones virtuales).

  1. Los métodos predeterminados han puesto fin al patrón clásico de interfaz y una clase complementaria que implementa la mayoría o todos los métodos en esa interfaz. Un ejemplo es Collection and AbstractCollection . Ahora deberíamos implementar los métodos en la propia interfaz para proporcionar funcionalidad predeterminada. Las clases que implementan la interfaz tienen la opción de anular los métodos o heredar la implementación predeterminada.
  2. Otro uso importante de los métodos predeterminados es la interface evolution . Supongamos que tengo un balón de clase como:

    public class Ball implements Collection { ... }

Ahora en Java 8 se ha introducido una nueva funcionalidad. Podemos obtener un flujo usando el método de stream agregado a la interfaz. Si el stream no fuera un método predeterminado, todas las implementaciones para la interfaz de la Collection se habrían roto, ya que no estarían implementando este nuevo método. Agregar un método no predeterminado a una interfaz no es source-compatible .

Pero supongamos que no recompilamos la clase y usamos un archivo jar antiguo que contiene esta clase Ball . La clase se cargará bien sin este método faltante, se pueden crear instancias y parece que todo funciona bien. PERO si el programa invoca el método de stream en la instancia de Ball obtendremos AbstractMethodError . Así que hacer el método por defecto resolvió ambos problemas.


Como se describe en this artículo,

Clases abstractas versus interfaces en Java 8

Después de introducir el Método predeterminado, parece que las interfaces y las clases abstractas son iguales. Sin embargo, todavía son conceptos diferentes en Java 8.

La clase abstracta puede definir al constructor. Son más estructurados y pueden tener un estado asociado con ellos. En contraste, el método predeterminado solo se puede implementar en los términos de invocar otros métodos de interfaz, sin referencia al estado de una implementación en particular. Por lo tanto, el uso para diferentes propósitos y la elección entre dos realmente depende del contexto del escenario.


Esto se describe en este article . Piense en forEach de las colecciones.

List<?> list = … list.forEach(…);

El forEach no está declarado por java.util.List ni por la interfaz java.util.Collection todavía. Una solución obvia sería simplemente agregar el nuevo método a la interfaz existente y proporcionar la implementación donde sea necesario en el JDK. Sin embargo, una vez publicado, es imposible agregar métodos a una interfaz sin romper la implementación existente.

El beneficio que brindan los métodos predeterminados es que ahora es posible agregar un nuevo método predeterminado a la interfaz y no rompe las implementaciones.


Estos dos son bastante diferentes:

Los métodos predeterminados son agregar funcionalidad externa a las clases existentes sin cambiar su estado.

Y las clases abstractas son un tipo normal de herencia, son clases normales que están destinadas a extenderse.


Hay algunas diferencias técnicas. Las clases abstractas todavía pueden hacer más en comparación con las interfaces de Java 8:

  1. La clase abstracta puede tener un constructor.
  2. Las clases abstractas son más estructuradas y pueden tener un estado.

Conceptualmente, el propósito principal de los métodos de defensa es una compatibilidad con versiones anteriores después de la introducción de nuevas características (como funciones lambda) en Java 8.


Hay mucho más para abstraer las clases que las implementaciones de los métodos predeterminados (como el estado privado), pero a partir de Java 8, cada vez que tenga la opción de elegir uno, debe elegir el método defensor (también conocido como default ) en la interfaz.

La restricción en el método predeterminado es que puede implementarse solo en términos de llamadas a otros métodos de interfaz, sin referencia al estado de una implementación en particular. Así que el caso de uso principal es de alto nivel y métodos de conveniencia.

Lo bueno de esta nueva característica es que, donde antes se veía obligado a usar una clase abstracta para los métodos de conveniencia, lo que restringía al implementador a una herencia única, ahora puede tener un diseño realmente limpio con la interfaz y un mínimo de implementación. Esfuerzo forzado en el programador.

La motivación original para introducir métodos default en Java 8 fue el deseo de ampliar las interfaces del Marco de Colecciones con métodos orientados a lambda sin romper ninguna implementación existente. Aunque esto es más relevante para los autores de las bibliotecas públicas, también puede encontrar la misma característica útil en su proyecto. Tiene un lugar centralizado donde agregar nuevas conveniencias y no tiene que confiar en cómo se ve el resto de la jerarquía de tipos.


Los métodos predeterminados en la Interfaz de Java se deben usar más para proporcionar una implementación ficticia de una función, por lo que se ahorra a cualquier clase de implementación de esa interfaz desde el dolor de declarar todos los métodos abstractos, incluso si quieren tratar solo uno. Los métodos predeterminados en la interfaz son, de este modo, más un reemplazo del concepto de clases de adaptadores.

Sin embargo, se supone que los métodos en clase abstracta brindan una implementación significativa que cualquier clase secundaria debería anular solo si es necesario para anular una funcionalidad común.


Los métodos predeterminados en la interfaz de Java permiten la evolución de la interfaz .

Dada una interfaz existente, si desea agregarle un método sin romper la compatibilidad binaria con versiones anteriores de la interfaz, tiene dos opciones a mano: agregar un método predeterminado o un método estático. De hecho, cualquier método abstracto agregado a la interfaz tendría que ser implícito por las clases o interfaces que implementan esta interfaz.

Un método estático es único para una clase. Un método predeterminado es único para una instancia de la clase.

Si agrega un método predeterminado a una interfaz existente, las clases e interfaces que implementan esta interfaz no necesitan implementarla. Ellos pueden

  • implemente el método predeterminado, y anula la implementación en la interfaz implementada.
  • volver a declarar el método (sin implementación) que lo hace abstracto.
  • no hacer nada (entonces el método predeterminado de la interfaz implementada simplemente se hereda).

Más sobre el tema here .


Por favor piense primero en principio abierto / cerrado. Los métodos por defecto en las interfaces LO VIOLAN. Esta es una mala característica en Java. Fomenta el mal diseño, la mala arquitectura, la baja calidad del software. Yo sugeriría evitar el uso de métodos predeterminados por completo.

Hágase algunas preguntas: ¿Por qué no puede poner sus métodos a la clase abstracta? ¿Necesitarías entonces más de una clase abstracta? Entonces piensa en de qué es responsable tu clase. ¿Está seguro de que todos los métodos que van a poner en la clase individual cumplen realmente el mismo propósito? Puede ser que distinga varios propósitos y luego divida su clase en varias clases, para cada propósito su propia clase.


Por qué tenemos que usar clase abstracta:

  1. La clase abstracta puede tener métodos abstractos y no abstractos.
  2. La clase abstracta no admite herencia múltiple.
  3. La clase abstracta puede tener variables finales, no finales, estáticas y no estáticas.
  4. La clase abstracta puede tener métodos estáticos, método principal y constructor.
  5. La clase abstracta puede proporcionar la implementación de la interfaz.
  6. La palabra clave abstracta se utiliza para declarar la clase abstracta.

Por qué tenemos que usar la interfaz:

  1. La interfaz es el nivel más abstracto de su diseño de aplicación
  2. La interfaz soporta herencia múltiple.
  3. Interfaz creada solo para describir firmas para subclases
  4. La interfaz solo tiene variables estáticas y finales.
  5. Use el método predeterminado solo para extender algunas interfaces, por ejemplo, lib externo. Pero sobre todo no es una buena práctica :)

Respecto a su consulta de

Entonces, ¿cuándo debería usarse la interfaz con los métodos predeterminados y cuándo debería usarse una clase abstracta? ¿Las clases abstractas siguen siendo útiles en ese escenario?

La documentation java proporciona la respuesta perfecta.

Clases abstractas comparadas a las interfaces:

Las clases abstractas son similares a las interfaces. No puede crear una instancia de ellos, y pueden contener una combinación de métodos declarados con o sin una implementación.

Sin embargo, con clases abstractas, puede declarar campos que no son estáticos y finales, y definir métodos concretos públicos, protegidos y privados.

Con las interfaces, todos los campos son automáticamente públicos, estáticos y finales, y todos los métodos que declara o define (como métodos predeterminados) son públicos. Además, puede extender solo una clase, sea o no abstracta, mientras que puede implementar cualquier número de interfaces.

Los casos de uso para cada uno de ellos se explicaron a continuación en la publicación de SE:

¿Cuál es la diferencia entre una interfaz y una clase abstracta?

¿Las clases abstractas siguen siendo útiles en ese escenario?

Sí. Todavía son útiles. Pueden contener métodos y atributos no estáticos, no finales ( protegidos, privados además de públicos ), lo que no es posible incluso con las interfaces Java-8.


La regla de Remi Forax es que no se diseña con clases abstractas. Usted diseña su aplicación con interfaces . Watever es la versión de Java, cualquiera que sea el lenguaje. Está respaldado por el principio de segregación de interfaz en los principios de SOLID

Más tarde puede usar clases abstractas para factorizar el código. Ahora con Java 8 puedes hacerlo directamente en la interfaz. Esta es una instalación, no más.