Menu
Coddy logo textTech

Por que não há Herança Múltipla de Classes

Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 26 de 87.

O Java impede deliberadamente que uma classe estenda mais de uma classe. Essa restrição existe devido a um problema conhecido como o Problema do Diamante.

Imagine se o Java permitisse herança múltipla. Considere este cenário hipotético:

// Este código NÃO é válido em 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");
    }
}

// NÃO é permitido em Java!
public class D extends B, C { }

Se você chamasse greet() em um objeto D, qual versão deveria ser executada? A de B ou a de C? Essa ambiguidade é o Problema do Diamante, nomeado após o formato de diamante formado pelo diagrama de herança.

A solução do Java é simples: permitir apenas a herança única de classes. No entanto, o Java fornece uma alternativa. Uma classe pode implementar múltiplas interfaces, sobre as quais você aprenderá em um capítulo futuro.

Interfaces resolvem o problema do diamante de forma diferente e oferecem flexibilidade sem a ambiguidade.

// Isso É válido em Java
public class Dog extends Animal implements Runnable, Comparable<Dog> {
    // Pode implementar múltiplas interfaces
}

Essa escolha de design mantém o modelo de herança do Java limpo e previsível, ao mesmo tempo em que permite uma poderosa reutilização de código através de interfaces.

challenge icon

Desafio

Fácil

Vamos construir um sistema de player de música que demonstra a regra de herança única do Java e mostra como você ainda pode alcançar designs flexíveis dentro dessa restrição.

Imagine que você deseja criar um alto-falante inteligente (smart speaker) que combina recursos de um player de música e de um assistente de voz. Como o Java não permite estender múltiplas classes, você precisará projetar sua hierarquia cuidadosamente usando herança única.

Você criará quatro arquivos para organizar seu código:

  • AudioDevice.java: Crie a classe base que todos os dispositivos de reprodução de áudio compartilham. Ela deve ter:
    • Um campo privado para deviceName (String)
    • Um construtor que aceita o nome do dispositivo
    • Um método getDeviceName() que retorna o nome
    • Um método playSound() que imprime: [deviceName]: Playing audio
  • MusicPlayer.java: Crie uma classe que estende AudioDevice e adiciona recursos específicos de música:
    • Um campo privado para currentSong (String)
    • Um construtor que recebe o nome do dispositivo e usa super(deviceName)
    • Um método setSong(String song) que define a música atual
    • Sobrescreva playSound() para imprimir: [deviceName]: Now playing - [currentSong]
  • SmartSpeaker.java: Crie uma classe que estende MusicPlayer (não ambos MusicPlayer e alguma classe VoiceAssistant - isso seria herança múltipla!). O smart speaker baseia-se no player de música adicionando recursos de voz:
    • Um campo privado para assistantName (String)
    • Um construtor que recebe o nome do dispositivo e o nome do assistente, usando super(deviceName)
    • Um método voiceCommand(String command) que imprime: [assistantName]: Processing "[command]"
    • Um método getFullInfo() que imprime: [deviceName] with [assistantName] assistant
  • Main.java: Demonstre sua cadeia de herança multinível. Você receberá três entradas: um nome de dispositivo (String), um nome de assistente (String) e um nome de música (String). Crie um SmartSpeaker, defina uma música e, em seguida, chame estes métodos em ordem:
    • getFullInfo()
    • playSound()
    • voiceCommand("skip to next")

Você receberá três entradas: o nome do dispositivo, o nome do assistente e o nome da música.

Observe como o SmartSpeaker ganha recursos de música ao estender MusicPlayer em uma cadeia (AudioDevice -> MusicPlayer -> SmartSpeaker), em vez de tentar estender várias classes não relacionadas. Esta é a abordagem do Java para manter a herança limpa e inequívoca!

Folha de consulta

O Java permite apenas herança única - uma classe pode estender apenas uma outra classe. Isso evita o Problema do Diamante, onde surge ambiguidade se uma classe pudesse herdar o mesmo método de múltiplas classes pai.

// NÃO permitido em Java - herança múltipla
public class D extends B, C { } // ERRO!

No entanto, o Java permite que uma classe implemente múltiplas interfaces como uma alternativa:

// Válido em Java
public class Dog extends Animal implements Runnable, Comparable<Dog> {
    // Pode estender uma classe e implementar múltiplas interfaces
}

O Java suporta herança multinível - criando cadeias de herança:

public class AudioDevice { }

public class MusicPlayer extends AudioDevice { }

public class SmartSpeaker extends MusicPlayer { }
// SmartSpeaker herda tanto de MusicPlayer quanto de AudioDevice

Experimente você mesmo

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Ler as entradas
        String deviceName = scanner.nextLine();
        String assistantName = scanner.nextLine();
        String songName = scanner.nextLine();
        
        // TODO: Criar um SmartSpeaker com deviceName e assistantName
        
        // TODO: Definir a música usando setSong()
        
        // TODO: Chamar getFullInfo()
        
        // TODO: Chamar playSound()
        
        // TODO: Chamar voiceCommand("skip to next")
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos