Menu
Coddy logo textTech

Por qué no hay herencia múltiple de clases

Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy. Lección 26 de 87.

Java impide deliberadamente que una clase extienda más de una clase. Esta restricción existe debido a un problema conocido como el Problema del Diamante.

Imagina si Java permitiera la herencia múltiple. Considera este escenario hipotético:

// Este código NO es válido en Java
public class A {
    public void greet() {
        System.out.println("Hello from A");
    }
}

public class B extends A {
    @Override
    public void greet() {
        System.out.println("Hello from B");
    }
}

public class C extends A {
    @Override
    public void greet() {
        System.out.println("Hello from C");
    }
}

// ¡NO está permitido en Java!
public class D extends B, C { }

Si llamaras a greet() en un objeto D, ¿qué versión debería ejecutarse? ¿La de B o la de C? Esta ambigüedad es el Problema del Diamante, llamado así por la forma de diamante que forma el diagrama de herencia.

La solución de Java es sencilla: permitir solo la herencia simple de clases. Sin embargo, Java proporciona una alternativa. Una clase puede implementar múltiples interfaces, sobre las cuales aprenderá en un próximo capítulo.

Las interfaces resuelven el problema del diamante de manera diferente y te brindan flexibilidad sin la ambigüedad.

// Esto ES válido en Java
public class Dog extends Animal implements Runnable, Comparable<Dog> {
    // Puede implementar múltiples interfaces
}

Esta elección de diseño mantiene el modelo de herencia de Java limpio y predecible, al mismo tiempo que permite una potente reutilización de código a través de interfaces.

challenge icon

Desafío

Fácil

Construyamos un sistema de reproductor de música que demuestre la regla de herencia simple de Java y muestre cómo aún puedes lograr diseños flexibles dentro de esta limitación.

Imagina que quieres crear un altavoz inteligente que combine funciones de un reproductor de música y de un asistente de voz. Como Java no permite extender varias clases, tendrás que diseñar cuidadosamente tu jerarquía usando herencia simple.

Crearás cuatro archivos para organizar tu código:

  • AudioDevice.java: Crea la clase base que comparten todos los dispositivos que reproducen audio. Debe tener:
    • Un campo privado para deviceName (String)
    • Un constructor que acepte el nombre del dispositivo
    • Un método getDeviceName() que devuelva el nombre
    • Un método playSound() que imprima: [deviceName]: Playing audio
  • MusicPlayer.java: Crea una clase que extienda AudioDevice y añada funciones específicas de música:
    • Un campo privado para currentSong (String)
    • Un constructor que reciba el nombre del dispositivo y use super(deviceName)
    • Un método setSong(String song) que establezca la canción actual
    • Redefine playSound() para que imprima: [deviceName]: Now playing - [currentSong]
  • SmartSpeaker.java: Crea una clase que extienda MusicPlayer (¡no tanto MusicPlayer como alguna clase VoiceAssistant; eso sería herencia múltiple!). El altavoz inteligente se basa en el reproductor de música al añadir funciones de voz:
    • Un campo privado para assistantName (String)
    • Un constructor que reciba el nombre del dispositivo y el nombre del asistente, usando super(deviceName)
    • Un método voiceCommand(String command) que imprima: [assistantName]: Processing "[command]"
    • Un método getFullInfo() que imprima: [deviceName] with [assistantName] assistant
  • Main.java: Demuestra tu cadena de herencia multinivel. Recibirás tres entradas: un nombre de dispositivo (String), un nombre de asistente (String) y un nombre de canción (String). Crea un SmartSpeaker, establece una canción y después llama a estos métodos en orden:
    • getFullInfo()
    • playSound()
    • voiceCommand("skip to next")

Recibirás tres entradas: el nombre del dispositivo, el nombre del asistente y el nombre de la canción.

Observa cómo SmartSpeaker obtiene capacidades musicales al extender MusicPlayer en una cadena (AudioDevice -> MusicPlayer -> SmartSpeaker), en lugar de intentar extender varias clases no relacionadas. ¡Este es el enfoque de Java para mantener la herencia limpia y sin ambigüedades!

Pruébalo tú mismo

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Leer las entradas
        String deviceName = scanner.nextLine();
        String assistantName = scanner.nextLine();
        String songName = scanner.nextLine();
        
        // TODO: Crear un SmartSpeaker con deviceName y assistantName
        
        // TODO: Establecer la canción usando setSong()
        
        // TODO: Llamar a getFullInfo()
        
        // TODO: Llamar a playSound()
        
        // TODO: Llamar a voiceCommand("skip to next")
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Java online