Java 8 permite la implementación predeterminada de métodos en interfaces llamadas Métodos predeterminados .
Estoy confundido entre cuándo usaría ese tipo de interface default method
, en lugar de un abstract class
(con abstract method(s)
).
Entonces, ¿cuándo se debe usar la interfaz con los métodos predeterminados y cuándo se debe usar una clase abstracta (con método (s) abstracto)? ¿Siguen siendo útiles las clases abstractas en ese escenario?
java
interface
java-8
abstract-class
default-method
Narendra Pathai
fuente
fuente
Respuestas:
Hay mucho más para las clases abstractas que las implementaciones de métodos predeterminadas (como el estado privado), pero a partir de Java 8, siempre que tenga la opción, debe ir con el
default
método defender (aka ) en la interfaz.La restricción del método predeterminado es que solo se puede implementar en términos de llamadas a otros métodos de interfaz, sin referencia al estado de una implementación en particular. Por lo tanto, el principal caso de uso son los métodos de mayor nivel y 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 limitaba al implementador a una herencia única, ahora puede tener un diseño realmente limpio con solo la interfaz y un mínimo de implementación esfuerzo forzado en el programador.
La motivación original para introducir
default
métodos en Java 8 fue el deseo de extender las interfaces de Framework 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. Tienes un lugar centralizado donde agregar nuevas comodidades y no tienes que depender de cómo se ve el resto de la jerarquía de tipos.fuente
Hay algunas diferencias técnicas. Las clases abstractas aún pueden hacer más en comparación con las interfaces Java 8:
Conceptualmente, el objetivo 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.
fuente
public static final
campos de una interfaz como "estado". Lastatic
parte significa que no están relacionados con una instancia particular en absoluto. Se asignan en la instanciación de clase , que no es lo mismo que después de la creación de la instancia .Esto se describe en este artículo . Piensa en las
forEach
colecciones.fuente
AbstractList::forEach
arrojar unUnsupportedOperationException
.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.
fuente
Como se describe en este artículo,
Clases abstractas versus interfaces en Java 8
fuente
En cuanto a su consulta de
La documentación de Java proporciona una respuesta perfecta.
Clases abstractas comparadas con las interfaces:
Los casos de uso para cada uno de ellos se explicaron en la siguiente publicación SE:
¿Cuál es la diferencia entre una interfaz y una clase abstracta?
Si. 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 interfaces Java-8.
fuente
Siempre que tengamos una opción entre la clase abstracta y la interfaz, siempre (casi) preferimos los métodos predeterminados (también conocidos como defensor o extensiones virtuales).
Collection and AbstractCollection
. Ahora deberíamos implementar los métodos en la interfaz misma para proporcionar la funcionalidad predeterminada. Las clases que implementan la interfaz tienen la opción de anular los métodos o heredar la implementación predeterminada.Otro uso importante de los métodos predeterminados es
interface evolution
. Supongamos que tuviera una clase Ball como:public class Ball implements Collection { ... }
Ahora en Java 8 se introduce una nueva característica de flujos. Podemos obtener una transmisión usando el
stream
método agregado a la interfaz. Sistream
no fuera un método predeterminado, todas las implementaciones para laCollection
interfaz se habrían roto ya que no estarían implementando este nuevo método. Agregar un método no predeterminado a una interfaz no lo essource-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 está funcionando bien. PERO si el programa invoca elstream
método en caso deBall
que lo obtengamosAbstractMethodError
. Por lo tanto, hacer que el método predeterminado resolviera ambos problemas.fuente
Los métodos predeterminados en la interfaz 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: agregar un método predeterminado o estático. De hecho, cualquier método abstracto agregado a la interfaz tendría que ser implementado por las clases o interfaces que implementan esta interfaz.
Un método estático es exclusivo de una clase. Un método predeterminado es exclusivo de 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
Más sobre el tema aquí .
fuente
Aunque es una vieja pregunta, permítanme dar mi opinión al respecto también.
clase abstracta: dentro de la clase abstracta podemos declarar variables de instancia, que se requieren para la clase secundaria
Interfaz: la interfaz interna de cada variable siempre es pública estática y final, no podemos declarar variables de instancia
clase abstracta: la clase abstracta puede hablar sobre el estado del objeto
Interfaz: la interfaz nunca puede hablar sobre el estado del objeto
clase abstracta: dentro de la clase abstracta podemos declarar constructores
Interfaz: Dentro de la interfaz no podemos declarar constructores ya que el propósito de los
constructores es inicializar las variables de instancia. Entonces, ¿cuál es la necesidad del constructor allí si no podemos tener variables de instancia en las interfaces ?
clase abstracta: dentro de la clase abstracta podemos declarar instancias y bloques estáticos
Interfaz: las interfaces no pueden tener bloques de instancia y estáticos.
clase abstracta: la clase abstracta no puede referirse a la expresión lambda
Interfaces: las interfaces con un método abstracto único pueden referirse a la expresión lambda
clase abstracta : dentro de la clase abstracta podemos anular los métodos de CLASE DE OBJETO
Interfaces: no podemos anular los métodos OBJECT CLASS dentro de las interfaces.
Terminaré con la nota de que:
Los conceptos de métodos predeterminados / conceptos de métodos estáticos en la interfaz llegaron solo para guardar clases de implementación pero no para proporcionar una implementación útil significativa. Métodos predeterminados / métodos estáticos son una especie de aplicación ficticia "si lo desea, puede usarlos o se los puede sustituir (en el caso de los métodos por defecto) en la clase de implementación" Por lo tanto salvándonos de la aplicación de nuevos métodos en clases de implementación cada vez que nuevos métodos en las interfaces Se agregan. Por lo tanto, las interfaces nunca pueden ser iguales a las clases abstractas.
fuente
La regla de Remi Forax es No diseñas con clases abstractas. Diseñas tu aplicación con interfaces . Watever es la versión de Java, sea cual sea el lenguaje. Está respaldada por la I principio de la segregación Nterface en SOL I D principios.
Más tarde puede usar las 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.
fuente
Compatibilidad con versiones anteriores: imagine que su interfaz es implementada por cientos de clases, modificando esa interfaz obligará a todos los usuarios a implementar el método recién agregado, aunque no sea 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.
fuente
En Java 8, una interfaz se parece a una clase abstracta, aunque puede haber algunas diferencias como:
1) Las clases abstractas son clases, por lo que no están restringidas a otras restricciones de la interfaz en Java, por ejemplo, la clase abstracta puede tener el estado , pero usted no puede tener el estado en la interfaz en Java.
2) Otra diferencia semántica entre la interfaz con métodos predeterminados y la clase abstracta es que puede definir constructores dentro de una clase abstracta , pero no puede definir el constructor dentro de la interfaz en Java
fuente
Los métodos predeterminados en la Interfaz Java se utilizarán más para proporcionar una implementación ficticia de una función, lo que salvará a cualquier clase de implementación de esa interfaz de la molestia de declarar todos los métodos abstractos, incluso si solo quieren tratar con uno. Por lo tanto, los métodos predeterminados en la interfaz son, en cierto modo, un reemplazo del concepto de clases de adaptador.
Sin embargo, se supone que los métodos en la clase abstracta brindan una implementación significativa que cualquier clase secundaria debe anular solo si es necesario para anular una funcionalidad común.
fuente
Como se mencionó en otras respuestas, se agregó la capacidad de agregar implementación a una interfaz para proporcionar compatibilidad con versiones anteriores en el marco de Colecciones. Yo diría que proporcionar compatibilidad con versiones anteriores es potencialmente la única buena razón para agregar implementación a una interfaz.
De lo contrario, si agrega implementación a una interfaz, está violando la ley fundamental de por qué las interfaces se agregaron en primer lugar. Java es un lenguaje de herencia único, a diferencia de C ++ que permite la herencia múltiple. Las interfaces proporcionan los beneficios de escritura que vienen con un lenguaje que admite la herencia múltiple sin presentar los problemas que vienen con la herencia múltiple.
Más específicamente, Java solo permite la herencia única de una implementación, pero sí permite la herencia múltiple de interfaces. Por ejemplo, el siguiente es un código Java válido:
MyObject
hereda solo una implementación, pero hereda tres contratos.Java transmitió la herencia múltiple de la implementación porque la herencia múltiple de la implementación viene con una serie de problemas espinosos, que están fuera del alcance de esta respuesta. Se agregaron interfaces para permitir la herencia múltiple de contratos (también conocidas como interfaces) sin los problemas de herencia múltiple de la implementación.
Para apoyar mi punto, aquí hay una cita de Ken Arnold y James Gosling del libro The Java Programming Language, cuarta edición :
fuente
Piense primero en el principio abierto / cerrado. Los métodos predeterminados 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. Sugeriría evitar usar completamente los métodos predeterminados.
Hágase algunas preguntas: ¿Por qué no puede poner sus métodos en la clase abstracta? ¿Necesitarías entonces más de una clase abstracta? Luego piense de qué es responsable su clase. ¿Estás seguro de que todos los métodos que vas a poner en la clase única realmente cumplen el mismo propósito? Puede ser que distinguirá varios propósitos y luego dividirá su clase en varias clases, para cada propósito su propia clase.
fuente