resueltos interfaz interfaces implementacion entre ejercicios ejemplo diferencia clases clase abstractas abstracta java interface abstract-class java-8 diamond-problem

interfaz - ¿Cuáles son las diferencias entre las clases abstractas y las interfaces en Java 8?



implementacion de clases abstractas en java (5)

Java 8, aunque introduce implementaciones predeterminadas para las interfaces, lo que significa que ya no es la diferencia crítica entre una interfaz y una clase abstracta.

Todavía hay algunas diferencias más críticas. Consulte esta publicación:

Interfaz con métodos predeterminados vs Clase abstracta en Java 8

¿Cómo evitan las nuevas interfaces Java 8 el problema del diamante?

Caso 1: está implementando dos interfaces, que tienen el mismo método default , debe resolver el conflicto en su clase de implementación .

interface interfaceA{ default public void foo(){ System.out.println("InterfaceA foo"); } } interface interfaceB{ default public void foo(){ System.out.println("InterfaceB foo"); } } public class DiamondExample implements interfaceA,interfaceB{ public void foo(){ interfaceA.super.foo(); } public static void main(String args[]){ new DiamondExample().foo(); } }

Arriba, el ejemplo produce a continuación:

InterfaceA foo

Caso 2: está extendiendo una clase base e implementando una interfaz con el método predeterminado. El compilador resuelve el problema del diamante por ti y no tienes que resolverlo como en el primer ejemplo.

interface interfaceA{ default public void foo(){ System.out.println("InterfaceA foo"); } } class DiamondBase { public void foo(){ System.out.println("Diamond base foo"); } } public class DiamondExample extends DiamondBase implements interfaceA{ public static void main(String args[]){ new DiamondExample().foo(); } }

El ejemplo anterior produce debajo del resultado:

Diamond base foo

En Java solía haber una diferencia sutil pero importante entre las clases abstractas y las interfaces: implementaciones predeterminadas . Las clases abstractas podrían tenerlos, las interfaces no podrían. Java 8, aunque introduce implementaciones predeterminadas para las interfaces, lo que significa que ya no es la diferencia crítica entre una interfaz y una clase abstracta.

¿Entonces que es?

Lo mejor que puedo decir es que la única diferencia que queda (además de tal vez un poco de eficiencia) es que las clases abstractas siguen la herencia única tradicional de Java, mientras que las interfaces pueden tener herencia múltiple (o implementación múltiple si se quiere). Esto me lleva a otra pregunta -

¿Cómo evitan las nuevas interfaces Java 8 el problema del diamante ?


Ahora que las interfaces pueden contener código ejecutable, los interfaces abarcan muchos casos de uso para clases abstractas. Pero las clases abstractas aún pueden tener variables miembro, mientras que las interfaces no pueden.

El problema del diamante se evita simplemente al no permitir que una clase implemente dos interfaces cuando ambas interfaces proporcionan una implementación predeterminada para el mismo método con la misma firma.


Hubo algunas respuestas muy detalladas, pero parecen faltar un punto que al menos considero como una de las pocas justificaciones para tener clases abstractas:

Las clases abstractas pueden tener miembros protegidos (y miembros con visibilidad predeterminada). Los métodos en las interfaces son implícitamente públicos .


La definición del problema del diamante es vaga. Hay todo tipo de problemas que pueden ocurrir con la herencia múltiple. Afortunadamente, la mayoría de ellos se pueden detectar fácilmente en tiempo de compilación, y los lenguajes de programación admiten soluciones simples para evitar estos problemas. La mayoría de estos problemas ni siquiera son específicos del problema de los diamantes . Por ejemplo, las definiciones conflictivas de métodos también pueden ocurrir sin diamantes :

interface Bar { default int test() { return 42; } } interface Baz { default int test() { return 6 * 9; } } class Foo implements Bar, Baz { }

El problema específico con los diamantes es la cuestión de inclusivo versus exclusivo . Si tiene una jerarquía de tipos donde B y C derivan de A y D deriva de B y C , entonces la pregunta es:

  • es D a B * y * a C (es decir, un tipo de A ), o
  • es D a B * o * a C (es decir, dos tipos de A ).

Bueno, en Java 8, el tipo A tiene que ser una interfaz . Entonces no hace ninguna diferencia, porque las interfaces no tienen ningún estado. No importa, las interfaces pueden definir métodos predeterminados , ya que tampoco tienen ningún estado. Pueden invocar métodos que tienen acceso directo al estado. Sin embargo, estos métodos siempre se implementan en base a herencia individual.


Las interfaces no pueden tener un estado asociado a ellas.

Las clases abstractas pueden tener un estado asociado a ellas.

Además, no es necesario implementar métodos predeterminados en las interfaces. De esta forma, no romperá el código ya existente, ya que mientras la interfaz recibe una actualización, la clase implementadora no necesita implementarla.
Como resultado, es posible que obtenga un código que no es óptimo, pero si desea tener un código más óptimo, entonces su trabajo es anular la implementación predeterminada.

Y, por último, en caso de que se produzca un problema con los diamantes, el compilador le advertirá y tendrá que elegir qué interfaz desea implementar.

Para mostrar más sobre el problema del diamante, considere el siguiente código:

interface A { void method(); } interface B extends A { @Override default void method() { System.out.println("B"); } } interface C extends A { @Override default void method() { System.out.println("C"); } } interface D extends B, C { }

Aquí obtengo el error de compilación en la interface D extends B, C , que:

interface D inherits unrelated defaults for method() form types B and C

La solución es:

interface D extends B, C { @Override default void method() { B.super.method(); } }

En caso de que quisiera heredar el method() de B
Lo mismo vale para si D fuera una class .

Para mostrar aún más sobre la diferencia entre interfaces y clases abstractas en Java 8, considere el siguiente Team :

interface Player { } interface Team { void addPlayer(Player player); }

En teoría, puede proporcionar una implementación predeterminada de addPlayer modo que pueda agregar jugadores a, por ejemplo, una lista de jugadores.
Pero espera...?
¿Cómo guardo la lista de jugadores?
La respuesta es que no puede hacer eso en una interfaz, incluso si tiene implementaciones predeterminadas disponibles.