Em java, não é permitido a utilização de herança múltipla, para que seja evitado vários problemas lógicos (Conflitos). Mas, para contornar este problema, foram criadas as interfaces. Elas, por sua vez, podem ser implementadas sem restrições de quantidade nas suas classes filhas croncretas ou abstratas. Ou seja, utilizando as interfaces o programador sairá dos limites da herança simples que o java oferece. Entretando, é necessário o entendimento da sutíl diferença entre interface e classes abstratas.

Interface

Interfaces são utilizadas para que contratos sejam definidos com toda as classe concretas que as implementem. Esses contratos são todos os métodos definidos na interface que precisarão ser implementados posteriormente. Porém, existem classes que não possuem esta obrigação; São as classes abstratas, que, por sua vez, possuem este nome por assumirem a responsabilidade de que nem todos os seus métodos serão implementados, passando a responsabilidade para a próxima classe concreta na árvore de herança.

Para um melhor entendimento das obrigações que uma interface impõe, utilizemos a interface Animal para todas as outras classes utilizadas neste artigo:

Listagem 1: Interface Animal


public interface Animal {

	public void setCor();
	
}

Através dela, foi definido o seguinte contrato: “Toda classe concreta que me implementar precisará definir o corpo do método setCor()”.

Porém, como supracitado, não é isso que acontece com uma classe abstrata:

Listagem 2: Classe abstrata Terrestre


public abstract class Terrestre implements Animal {
	
	public abstract void rastejar();

}

Como notado, não foi necessária a implementação dos métodos de Animal. Antes que seja perguntado, não haverá problemas caso a classe Terrestre seja instanciada pois, como ela é abstract, ela não poderá ser instanciada! Veja na imagem a seguir:

Tentativa frustada de instanciar uma classe abstrata

Figura 1: Tentativa frustada de instanciar uma classe abstrata.

Ou seja, o que ela fez, neste caso, foi adicionar mais um método que a próxima classe concreta na árvore de herança deverá implementar. Por exemplo, digamos que exista uma classe concreta Cobra:

Listagem 3: Classe Cobra


public class Cobra extends Terrestre{

	@Override
	public void setCor() {
		// Aqui será setada a cor do animal
		
	}

	@Override
	public void rastejar() {
		System.out.println("rastejando......");
		
	}

}

Várias coisas interessantes aconteceram nesta classe.

Primeiro: Prestem bem atenção que para utilizar uma classe abstrata a palavra chave utilizada é extends, que difere da palavra utilizada para interface, como veremos depois.

Segundo: Como Cobra é a primeira classe concreta na árvore de herança, ela deve implementar todos os métodos de classes abstratas e interfaces acima dela. No nosso caso, Cobra teve que implementar 1 método da classe abstrata Terrestre “rastejar()” e 1 método da interface Animal “setCor().

Mas, e se existir um animal que não tenha classificação e tudo que sabemos é que ele É-UM Animal? Simples, apenas utilizaremos a interface Animal! Veja:

Listagem 4: Utilizando a inteface Animal


public class AnimalNaoIdentificado implements Animal{

	@Override
	public void setCor() {
		// Será setada a cor do animal.
		
	}

}

Simples, não?! Uma vez que o único contrato feito foi com a interface, a classe AnimalNaoIdentificado precisou implementar apenas os métodos da Interface Animal. Podemos notar, também, que para utilizar um interface é necessário a utilização da palavra-chave implements.

Agora, como utilizaríamos as duas coisas juntas? Interface e classe Abstrata?

A pequena diferença entre classe abstrata e interface é que, na primeira, pode-se implementar alguns métodos e outros não. Já na segunda, jamais poderá ser implementado qualquer método. Ou seja, na interface, todos os métodos serão obrigatoriamente implementados pelas classes (concretas) filhas.

Sendo assim, tenhamos como exemplo uma classe abstrata Domestico, que não implementa a interface Animal:

Listagem 5: Classe abstrata Domestico


public abstract class Domestico {
	
	public void senta()
	{
		System.out.println("Estou sentando....");
	}
	
	public abstract void deita();

}

Note que não há qualquer ligação entre esta classe abstrata e interface Animal. Sabendo disto, em uma classe concreta utilizando as 2 teremos:

Listagem 6: Classe concreta que utiliza classe abstrata e interface


public class Cachorro extends Domestico implements Animal{

	@Override
	public void setCor() {
		//Setando cor do cachorro...
		
	}

	@Override
	public void deita() {
		System.out.println("Deitando.. E, depois, vou sentar!");
		this.senta();		
	}

}

A classe Cachorro utilizou a herança simples mais os benefícios da interface. E foi para isto que ela foi criada, para auxiliar os desenvolvedores que precisam de algum sistema similar a herança múltipla.

Existem algumas observações sobre interface:

  • Uma classe não pode extender múltiplas classe, mas poderá implementar mais de uma inteface;
  • Uma inteface pode extender ( extends ) várias outras, mas nunca implementar (implements) uma.
  • Junção de todas as classes no sistema

    Figura 2: Junção de todas as classes no sistema.

    Com isto, finalizo o meu artigo. Espero que todos tenham compreendido como utilizar e aproveitar os benefícios que vieram com as interfaces.

    Abraço!