quarta-feira, 5 de dezembro de 2007

Herança múltipla no Java

É um assunto já bem manjado, milhões de explicações pela internet, mas sempre aparece alguém dizendo que Java não tem herança multipla. Bem, é verdade, não existe, mas isso não quer dizer que não da para fazer. Segue um exemplo de como da para fazer herança múltipla com Java utilizando interfaces e agregação.

Considere uma interface que define um animal, não vou complicar enxendo de métodos, portanto vou tentar ser o mais simples possivel. Todo animal come portanto essa interface irá definir um método comer:

Animal.java

public interface Animal {
 void comer();
}

Vou criar agora duas novas interfaces, uma que define gatos e outra que define cachorros, sendo que ambas são animais também (claro).

Gato.java

public interface Gato extends Animal {
    void miar();
}
Cachorro.java
public interface Cachorro extends Animal {
    void latir();
}

Feito isso, implemento duas classes concretas: um gato (o gato siamês) e um cachorro (pastor alemão). Até ai tudo bem, nada de diferente ou de herança múltipla.

GatoSiames.java

public class GatoSiames implements Gato {
    public void miar() {
        System.out.println("miando");
    }
    
    public void comer() {
        System.out.println("gato comendo");
    }
}
PastorAlemao.java
public class PastorAlemao implements Cachorro {
    public void latir() {
        System.out.println("latindo");
    }
    
    public void comer() {
        System.out.println("cachorro comendo");
    }
}

Agora sim, começaremos as bizarrices, supondo que meu pastor alemão se engraçou com uma gata siamesa, no meu mundo isso é possível. No meu mundo também, a mãe é que da a característica principal do filho, ou seja, qualquer criatura que nasce de uma gata vai se parecer mais com um gato e qualquer coisa que nasce de uma cadela vai se parecer mais um cachorro. Logo, de acordo com as regras do meu mundo, quando o pastor alemão cruzou com a gata siamesa, nasceu uma criatura que se parece com um gato siamês, mas tem também características de um pastor alemão, ou seja, ela tem que herdar comportamento de ambas classes, mas as características de animal (comer), isso ela herda da mãe mesmo. Veja como usando interface e agregação é fácil modelar essa espécie bizarra:

GatoBizarro.java

public class GatoBizarro extends GatoSiames implements Cachorro {
    private PastorAlemao cachorro = new PastorAlemao();
    
    public void latir() {
        cachorro.latir();
    }
}

Perceba que se eu mandar esse bixo comer, ele vai comer feito um gato, na real ele pode ser considerado um gato pois sabe miar. Porem como é um filho de um cachorro, ele pode ser considerado como cachorro também pois sabe latir (e lati feito um pastor alemão), mas mesmo olhando para ele como um cachorro, comer que é o comportamento em comum entre todos animais, isso ele faz como um gato mesmo.

Agora vamos fazer o contrario, um gato siamês pulou a cerca com uma pastora alemã (como ele deu conta, ninguém sabe). Como eu já disse, quem manda na característica principal é a fêmea, logo nasceu algo parecido com cachorro. Eis a classe que representa essa criatura:

public class CachorroBizarro extends PastorAlemao implements Gato {
    private GatoSiames gato = new GatoSiames();
    
    public void miar() {
        gato.miar();
    }
}

Esse cara ai come feito cachorro, lati feito cachorro, mas sabe miar feito um gato siamês ;).

Viu como é fácil, usando de agregação e delegando ao objeto agregado é possível e fácil fazer herança múltipla com Java.