DEV Community

FUNDAMENTOS JAVA
FUNDAMENTOS JAVA

Posted on

4.4 Herança múltipla? Não.

Herança Múltipla e Métodos Default

Embora pareça que os métodos default introduzam herança múltipla, eles não fazem isso no sentido clássico. O Java continua sem suportar herança múltipla de implementação (como em C++ e python).

Isso porque:

  • Interfaces não têm estado – métodos default não podem acessar atributos de instância, pois interfaces não possuem campos.

  • Resolução de conflitos é bem definida – Se uma classe implementar duas interfaces com o mesmo método default, ela é obrigada a sobrescrevê-lo para resolver a ambiguidade.

Exemplo de Conflito e Solução

interface A {
    default void metodo() {
        System.out.println("Método de A");
    }
}

interface B {
    default void metodo() {
        System.out.println("Método de B");
    }
}

class C implements A, B {
    @Override
    public void metodo() {
        A.super.metodo(); // Ou B.super.metodo()
    }
}

Enter fullscreen mode Exit fullscreen mode

A classe C precisa sobrescrever metodo() e definir qual versão deseja usar.

Por que não é Herança Múltipla?

  • No C++ e no Python (por exemplo), uma classe pode herdar implementações de múltiplas classes. Isso cria problemas sérios de ambiguidade e compartilhamento de estado.
  • No Java, a solução foi permitir apenas herança de comportamento, mas não de estado.

Comparação:

Image description

Lambdas e Métodos Default

Os lambdas também foram introduzidos no Java 8, principalmente para programação funcional. Eles se encaixam bem com interfaces funcionais (@FunctionalInterface), que contêm apenas um método abstrato.
Os métodos default não quebram essa regra, pois não são considerados métodos abstratos.

@FunctionalInterface
interface Operacao {
    int executar(int a, int b);

    default void imprimirResultado(int a, int b) {
        System.out.println("Resultado: " + executar(a, b));
    }
}

public class Main {
    public static void main(String[] args) {
        Operacao soma = (a, b) -> a + b;
        soma.imprimirResultado(3, 5);
    }
}

Enter fullscreen mode Exit fullscreen mode

Aqui, executar() é o método abstrato (necessário para ser uma interface funcional), mas imprimirResultado() é default, o que permite reutilizar código sem quebrar a estrutura funcional.

O Trade-Off e os Argumentos de Brian Goetz
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html

Como mencionado, Brian Goetz (Java Language Architect) e outros líderes enfatizam que métodos default não foram criados para implementar mixins ou herança múltipla, mas sim para evolução segura de APIs. Na seção 10 do documento, eles destacam:

Acoplamento vs. Flexibilidade: Métodos default aumentam o acoplamento entre interfaces e implementações, mas isso é mitigado pela impossibilidade de acessar estado e pela necessidade de resolução explícita de conflitos.

Design Conservador: Java optou por uma abordagem que prioriza a compatibilidade e a segurança, evitando os "usos nocivos" de herança múltipla (como em C++).

Impacto no Java 23 (e além)

Mesmo nas versões mais recentes do Java (como a 23), o modelo de métodos default mantém as mesmas restrições, reforçando que interfaces continuam sendo contratos de comportamento, não de estado. Novas features (como métodos privados em interfaces) foram adicionadas para melhorar a organização do código, mas não alteram esse princípio.

Exemplo de evolução recente (Java 9+):

interface Logging {
    private void log(String message) { // Método privado (Java 9+)
        System.out.println("[LOG] " + message);
    }

    default void debug(String message) {
        log("DEBUG: " + message);
    }
}
Enter fullscreen mode Exit fullscreen mode

Quando Usar Métodos Default?

  • Evolução de APIs: Adicione novos métodos a interfaces sem quebrar implementações existentes.
  • Compartilhamento de código comum: Implementar comportamentos genéricos que podem ser reutilizados por múltiplas classes.
  • Evitar duplicação: Centralizar lógica repetida em interfaces (ex: validações, logging).

Conclusão

  • Métodos default não são herança múltipla, mas uma forma de evolução de interfaces.
  • Não há compartilhamento de estado, pois interfaces não possuem atributos de instância.
  • Resolução de conflitos é explícita, exigindo que a classe defina qual método usar.
  • Lambdas e interfaces funcionais coexistem bem com default, pois esses métodos não interferem na natureza da interface funcional.

Os métodos default são uma ferramenta pragmática para resolver problemas de evolução de APIs, com restrições intencionais para evitar complexidade excessiva. O Java prioriza a segurança e a clareza, mesmo que isso limite flexibilidade em comparação a outras linguagens.

Para cenários que exigem compartilhamento de estado ou comportamentos mais complexos, outras abordagens são recomendadas (ex: composição, padrões de projeto como Strategy ou Decorator).

Top comments (0)