Interfaces

Uma interface em Java é, tal como uma classe, um tipo de dados de referência.
Tal como uma classe uma interface pode ter constantes e métodos, sendo que os métodos de uma interface são todos implicitamente abstratos, possuindo somente assinatura, sem corpo.
Uma interface define o comportamento (o conjunto de métodos) que uma classe implementa.
Uma interface é declarada com a palavra reservada interface:

public interface ICirculo {
   public static final double PI = 3.14; 
   public double area(double raio); 
   public double perimetro(double raio);
}

A interface ICirculo possui uma constante PI e dois métodos abstratos: area() e perimetro().
Uma interface é implementada por uma classe, sendo que uma classe pode implementar uma ou mais interfaces:
Uma classe implementa uma interface com a palavra reservada implements:

public class Circulo implements ICirculo 
{ 
   public double area(double raio) { 
      return PI * raio * raio; 
   } 

   public double perimetro(double raio) { 
      return 2 * PI * raio; 
   } 
} 

Como se pode ver, a classe Circulo ao implementar a interface ICirculo tem, obrigatoriamente, de implementar todos os métodos abstratos da interface.
Como foi dito atrás, uma classe pode implementar várias interfaces, sendo obrigada a implementar todos os métodos abstratos de todas elas.
Consideremos a interface IGraphics:

public interface IGraphics { 
   public void drawCircle(double raio); 
} 

A classe Circulo pode implementar as interfaces ICirculo e IGraphics:

public class Circulo implements ICirculo, IGraphics 
{ 
   public void drawCircle(double raio) { 
      System.out.println("Draw circle"); 
   } 
   public double area(double raio) { 
      return PI * raio * raio; 
   } 
   public double perimetro(double raio) { 
      return 2 * PI * raio; 
   } 
} 

Características das interfaces:

  • Uma interface pode ter um numero ilimitado de métodos, sendo que todos são implicitamente abstratos.
  • Todos os métodos de uma interface são implicitamente públicos.
  • Uma interface não tem construtores porque não é uma classe.
  • Uma interface só pode ter campos ao mesmo tempo static e final.
  • Uma interface não pode ser instanciada.

Tal como foi dito, uma interface é um tipo de dados de referência pelo pode ser usada para declarar uma variável:
ICirculo circulo;
No entanto, só podemos instanciar um objeto nesta variável com a classe que implementa a interface, neste caso, Circulo:
ICirculo circulo = new Circulo();
Nesta situação, os métodos a que temos acesso são os da interface ICirculo, para além, claro, dos herdados da classe Object.

Herança entre interfaces

Tal como nas classes, o mecanismo de herança também se aplica a interfaces.
Tal como nas classes, uma interface pode herdar de outra através da palavra reservada extends:

public interface ICapuccino { 
     
    public void tiraCafeCapuccino(); 
     
} 
 
public interface IExpresso extends ICapuccino { 
     
    public void tiraCafeExpresso(); 
     
} 

A interface IExpresso herda o método tiraCafeCapuccino() da interface ICapuccino.
Se tivermos uma classe MaquinaCafe que implemente a interface IExpresso, ela terá de implementar os dois métodos: tiraCafeCapuccino() e tiraCafeExpresso():

public class MaquinaCafe implements IExpresso{ 
 
    public void tiraCafeExpresso() { 
        System.out.println("Tira cafe expresso"); 
    } 
 
    public void tiraCafeCapuccino() { 
        System.out.println("Tira cafe capuccino"); 
    } 
} 

Polimorfismo de interfaces

O polimorfismo de interfaces ocorre quando uma classe implementa várias interfaces e um objecto dessa classe é instanciado com o tipo de referência de uma das interfaces.
Nesse caso, o objeto só executa os métodos dessa interface. O mesmo acontece se fôr instanciado com os tipos das outras interfaces. É como se o objeto mudasse de forma.

Exemplo:
Imaginemos que temos 3 interfaces: IPintor, IElectrecista e ICanalizador.

public interface IPintor { 
    void pinta(); 
} 
 
public interface IElectrecista { 
    void mudaLampada(); 
} 
 
public interface ICanalizador { 
    void desentopeCano(); 
} 

Agora temos a classe Empregado que implementa as 3 interfaces:

public class Empregado implements IPintor, ICanalizador, 
IElectrecista{ 
 
    public void pinta() { 
        System.out.println("Pinta"); 
    } 
 
    public void desentopeCano() { 
        System.out.println("Desentope cano"); 
    } 
 
    public void mudaLampada() { 
        System.out.println("Muda lampada"); 
    } 
     
} 

Agora criemos instâncias da classe Empregado mas com o tipo de de cada uma das interfaces:

    public static void main(String[] args) { 
         
        IPintor pintor = new Empregado(); 
        pintor.pinta(); 
         
        ICanalizador canalizador = new Empregado(); 
        canalizador.desentopeCano(); 
         
        IElectrecista electricista = new Empregado();
        electricista.mudaLampada(); 
}

Criámos 3 objetos da classe Empregado mas com os tipos de cada uma das interfaces e verificamos que cada um desses objetos muda de forma em relação aos ouros, ou seja o objeto pintor só acede ao método da interface IPintor, o objeto canalizador só acede ao método da interface ICanalizador e o objeto eletricista só acede ao método da interface IElectrecista. É isto o polimorfismo de interfaces.