Resolución de conflictos durante la herencia múltiple en Java

Una clase puede implementar múltiples interfaces en java, pero ¿qué sucede si las múltiples interfaces predeterminadas implementadas tienen métodos predeterminados con las mismas firmas? Luego, en la clase de implementación, cuál de las implementaciones predeterminadas se invocaría desde las diversas interfaces principales.

Los diseñadores de Java 8 han estado pensando en este conflicto y han especificado reglas de resolución para tales escenarios. Veamos ahora los posibles escenarios de conflicto y las reglas de resolución desarrolladas en Java 8 para evitarlos.

Las reglas de resolución de conflictos para los métodos predeterminados heredados en orden de prioridad son las siguientes

  • Regla 1: las clases tienen mayor prioridad que las interfaces
  • Regla 2: las interfaces o subinterfaces derivadas tienen mayor prioridad que las interfaces más arriba en la jerarquía de herencia
  • Regla 3: En caso de que la Regla 1 y la Regla 2 no puedan resolver el conflicto, la clase implementadora tiene que anular específicamente y proporcionar un método con la misma definición de método.

Ahora discutámoslos uno por uno para entender el flujo de trabajo interno de las reglas. 

Implementación:

Regla 1  Las clases tienen mayor prioridad que las interfaces 

Ejemplo 

Java

// Java Program to illustrate
// classes take higher precedence than interfaces
 
// Importing input output classes
import java.io.*;
 
// Interface 1
interface A {
    public default void m1()
    {
        System.out.println("m1 method of interface m1");
    }
}
 
// Interface 2
interface B {
    public default void m1()
    {
        System.out.println("m1 method of interface B");
    }
}
 
// Helper class
class D {
 
    // Main driver method
    public void m1()
    {
 
        // Print statement when m1() of classD is called
        System.out.println("method of class D");
    }
}
 
// Main class
// It is implementing both the interfaces A and B
class C extends D implements A, B {
 
    // Main driver method
    public static void main(String args[])
    {
        // Creating an object of this class
        // in the mai() method
        C c = new C();
 
        // Calling the method over the object created
        // to illustrate Classes take higher precedence
        // than interfaces
        c.m1();
    }
}

Producción:

method of class D

Explicación de salida:

Dado que la clase C hereda el método predeterminado m1() de la interfaz A, la interfaz B y la superclase C. Si se invoca el método m1() en la clase C, se ejecuta la implementación en la superclase C.

Regla 2  Las interfaces o subinterfaces derivadas tienen mayor prioridad que las interfaces más arriba en la jerarquía de herencia

Ejemplo

Java

// Java Program to illustrate Derived interfaces or
// sub-interfaces take higher precedence than the interfaces
// higher-up in the inheritance hierarchy
 
// Interface 1
interface A {
 
    // Method of Interface 1
    public default void m1()
    {
 
        // Execution command whenever
        // interface 1 is called
        System.out.println("m1 method of A");
    }
}
 
// Interface 2
// This interface is extending above interface
interface B extends A {
 
    // Method of Interface 1
    public default void m1()
    {
 
        // Execution command whenever
        // interface 2 is called
        System.out.println("m1 method of B");
    }
}
 
// Main class
// Which is implementing Interface 2
class C implements B {
 
    // Main driver method
    public static void main(String args[])
    {
        // Creating an object of this class
        // in the main method
        C c = new C();
 
        // Calling method over class object
        // created above to illustrate sub-interface
        // has higher precedence
        c.m1();
    }
}
Producción

m1 method of B

Explicación de salida:

Dado que la interfaz B hereda de la interfaz A. Ambos tienen un método predeterminado m1() con la misma firma. La clase C implementa ambas interfaces A y B. Cuando se invoca el método m1() en una instancia de la clase C, se invoca la implementación en la interfaz B, ya que es la interfaz secundaria más baja/más derivada en la jerarquía de herencia.

Regla 3 En caso de que la Regla 1 y la Regla 2 no puedan resolver el conflicto, la clase implementadora tiene que anular específicamente y proporcionar un método con la misma definición de método

Ejemplo 

Java

// Java Program to in which implementing class
// has to specifically override and provide a method
// with the same method definition
// to resolve the conflice
 
// Importing input output classes
import java.io.*;
 
// Interface 1
interface A {
 
    // m1() method of Interface 1/A
    public default void m1()
    {
        System.out.println("m1 method of interface m1");
    }
}
 
// Interface 2
interface B {
 
    // m1() method of Interface 2/B
    public default void m1()
    {
        System.out.println("m1 method of interface B");
    }
}
 
// Main Class
// This class implements both the interfaces
class C implements A, B {
 
    // Method 1
    // m1() method of class C (This class)
    public void m1()
    {
 
        // Super keyword called over m1() method
        // for interface 2/B
        B.super.m1();
    }
 
    // Method 2
    // Main driver method
    public static void main(String args[])
    {
        // Creating an object of this class
        // in the main() method
        C c = new C();
 
        // Calling the method 'm1()'
        // over the class object
        // in the main method()
        c.m1();
    }
}

Producción:

m1 method of interface B

Explicación de salida:

  • Para obtener el comportamiento deseado, la clase de implementación puede, por supuesto, invocar el método predeterminado específico desde la interfaz principal específica. Pero la clase aún necesita anular el método predeterminado para resolver el conflicto e invocarlo.
  • La clase C hereda de las interfaces A y B del ejemplo anterior, todas las cuales tienen las implementaciones m1() predeterminadas(). Como todas las interfaces A y B son padres de C, están en el mismo nivel de la jerarquía, y C también debe implementar el método m1() por su cuenta().

Nota: La implementación del método print() de Inside Class C debe invocar la implementación específica de la interfaz A o B. Para esto, Java 8 tiene una sintaxis especial de la siguiente manera:

<super-interface-name>.super<method-name>

En este caso, el método m1() en la clase C invocará el método m1() de B, su padre, así: B.super.m1()

Publicación traducida automáticamente

Artículo escrito por sachinchhipa44 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *