Java y herencia múltiple

La herencia múltiple es una característica de un concepto orientado a objetos, donde una clase puede heredar propiedades de más de una clase principal. El problema ocurre cuando existen métodos con la misma firma tanto en la superclase como en la subclase. Al llamar al método, el compilador no puede determinar a qué método de clase llamar e incluso al llamar qué método de clase tiene prioridad. 

Nota: Java no admite la herencia múltiple

Ejemplo 1:

Java

// Java Program to Illustrate Unsupportance of
// Multiple Inheritance
 
// Importing input output classes
import java.io.*;
 
//  Class 1
// First Parent class
class Parent1 {
 
  // Method inside first parent class
  void fun() {
 
    // Print statement if this method is called
    System.out.println("Parent1");
  }
}
 
// Class 2
// Second Parent Class
class Parent2 {
 
  // Method inside first parent class
  void fun() {
 
    // Print statement if this method is called
    System.out.println("Parent2");
  }
}
 
// Class 3
// Trying to be child of both the classes
class Test extends Parent1, Parent2 {
 
  // Main driver method
  public static void main(String args[]) {
 
    // Creating object of class in main() method
    Test t = new Test();
 
    // Trying to call above functions of class where
    // Error is thrown as this class is inheriting
    // multiple classes
    t.fun();
  }
}

Salida: se lanza un error de compilación

Conclusión: como se muestra en el código anterior, al llamar al método fun() usando el objeto Test, se generarán complicaciones, como llamar al método fun() de Parent1 o al método fun() de Parent2. 

Ejemplo 2:

          GrandParent
           /     \
          /       \
      Parent1      Parent2
          \       /
           \     /
             Test

El código es el siguiente

Java

// Java Program to Illustrate Unsupportance of
// Multiple Inheritance
// Diamond Problem Similar Scenario
 
// Importing input output classes
import java.io.*;
 
//  Class 1
// A Grand parent class in diamond
class GrandParent {
 
  void fun() {
 
    // Print statement to be executed when this method is called
    System.out.println("Grandparent");
  }
}
 
// Class 2
// First Parent class
class Parent1 extends GrandParent {
  void fun() {
 
    // Print statement to be executed when this method is called
    System.out.println("Parent1");
  }
}
 
// Class 3
// Second Parent Class
class Parent2 extends GrandParent {
  void fun() {
 
    // Print statement to be executed when this method is called
    System.out.println("Parent2");
  }
}
 
// Class 4
// Inheriting from multiple classes
class Test extends Parent1, Parent2 {
 
  // Main driver method
  public static void main(String args[]) {
 
    // Creating object of this class i main() method
    Test t = new Test();
 
    // Now calling fun() method from its parent classes
    // which will throw compilation error
    t.fun();
  }
}

Producción: 

Nuevamente arroja un error del compilador cuando el método run() ya que las herencias múltiples causan un problema de diamante cuando se permite en otros lenguajes como C++. A partir del código, vemos que: Al llamar al método fun() utilizando el objeto Test, se producirán complicaciones, como llamar al método fun() de Parent1 o al método fun() de Child. Por lo tanto, para evitar tales complicaciones, Java no admite herencias múltiples de clases.

La herencia múltiple no es compatible con Java usando clases, manejar la complejidad que causa debido a las herencias múltiples es muy complejo. Crea problemas durante varias operaciones como la conversión, el enstringmiento de constructores, etc., y la razón principal es que hay muy pocos escenarios en los que realmente necesitamos herencias múltiples, por lo que es mejor omitirlo para mantener las cosas simples y directas.
  
¿Cómo se manejan los problemas anteriores para los métodos e interfaces predeterminados
Java 8 admite métodos predeterminados donde las interfaces pueden proporcionar una implementación predeterminada de métodos. Y una clase puede implementar dos o más interfaces. En caso de que ambas interfaces implementadas contengan métodos predeterminados con la misma firma de método, la clase de implementación debe especificar explícitamente qué método predeterminado se utilizará o debe anular el método predeterminado. 

Ejemplo 3:

Java

// Java program to demonstrate Multiple Inheritance
// through default methods
 
// Interface 1
interface PI1 {
 
    // Default method
    default void show()
    {
 
        // Print statement if method is called
        // from interface 1
        System.out.println("Default PI1");
    }
}
 
// Interface 2
interface PI2 {
 
    // Default method
    default void show()
    {
 
        // Print statement if method is called
        // from interface 2
        System.out.println("Default PI2");
    }
}
 
// Main class
// Implementation class code
class TestClass implements PI1, PI2 {
 
    // Overriding default show method
    public void show()
    {
 
        // Using super keyword to call the show
        // method of PI1 interface
        PI1.super.show();
 
        // Using super keyword to call the show
        // method of PI2 interface
        PI2.super.show();
    }
 
    // Mai driver method
    public static void main(String args[])
    {
 
        // Creating object of this class in main() method
        TestClass d = new TestClass();
        d.show();
    }
}
Producción

Default PI1
Default PI2

Nota: si eliminamos la implementación del método predeterminado de «TestClass», obtenemos un error de compilación. Si hay un diamante a través de las interfaces, entonces no hay problema si ninguna de las interfaces intermedias proporciona la implementación de la interfaz raíz. Si proporcionan implementación, entonces se puede acceder a la implementación como se indicó anteriormente usando la palabra clave super.

Ejemplo 4:

Java

// Java program to demonstrate How Diamond Problem
// Is Handled in case of Default Methods
 
// Interface 1
interface GPI {
 
    // Default method
    default void show()
    {
 
        // Print statement
        System.out.println("Default GPI");
    }
}
 
// Interface 2
// Extending the above interface
interface PI1 extends GPI {
}
 
// Interface 3
// Extending the above interface
interface PI2 extends GPI {
}
 
// Main class
// Implementation class code
class TestClass implements PI1, PI2 {
 
    // Main driver method
    public static void main(String args[])
    {
 
        // Creating object of this class
        // in main() method
        TestClass d = new TestClass();
 
        // Now calling the function defined in interface 1
        // from whom Interface 2and 3 are deriving
        d.show();
    }
}
Producción

Default GPI

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 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 *