Ir para o conteúdo

Interfaces

Uma interface permite definir um contrato para determinados objectos, isto é, uma interface permite que o programador indique um conjunto de métodos que terão de ser respeitados por todas as classes que implementem a interface.

O mecanismo de interfaces encontra-se à parte do sistema normal de herança e de classes do Java, embora exista herança entre interfaces, devido às particularidades das interfaces, não funciona exactamente do mesmo modo. Além disso, as interfaces permite contornar, até certo ponto, a não existência de herança múltipla.

No fundo, uma interface é apenas um conjunto de métodos agrupados logicamente, que garantem ao programador que todas as classes que implementem a interface irão ter esses métodos definidos.

Interfaces em Java

Uma interface apenas pode conter definições de métodos, atributos estáticos e tipos internos1. Por outras palavras, não podem existir atributos de instância, não pode existir código dentro dos métodos, não pode existir nada na interface para o qual seja necessário instanciar a interface. As interfaces não podem ser instanciadas.

Devido à natureza das interfaces, não podem existir elementos privados dentro da interface, isto implica que todos os métodos e atributos estáticos são públicos e a herança entre interfaces, embora possível, apenas passa as definições de métodos.

Uma classe pode implementar várias interfaces, tendo para isso que implementar todos os métodos que as interfaces definem. Se a classe não implementar todos os métodos terá de ser declarada como abstracta e os métodos deverão ser implementados pela primeira classe não abstracta que surja ao descer na hierarquia.

As interfaces surgem por vezes com o papel de marcadores. Estes marcadores são interfaces sem qualquer código, seja referente a definição de métodos ou atributos estáticos, e que são usados para identificar se uma determinada classe é de um determinado tipo. Por exemplo, a interface Serializable, não possui atributos estáticos, declarações de métodos ou tipos internos, é uma interface vazia, mas é usada pelo sistema de serialização. Todos os objectos que queriam ser serializados devem implementar esta interface, apesar dela não obrigar a implementar método algum2.

Código

public interface ComandoUniversal {

    //Não é colocado modificador de acesso, todos os métodos são públicos
    void ligar();
    void desligar();
    void mudarCanal(int canal);
    void pause();
    void start();
    void stop();
    void semBaterias();
}

//Herança entre interfaces: todos os métodos definidos na interface ComandoUniversal são herdados por esta nova interface
public interface ComandoUniversal2 extends ComandoUnivesal {

    int mostrarCanal();
}

public class ComandoTelevisao implements ComandoUniversal {

    //aqui já estão definidos os modificadores de acesso
    public void ligar() {
    }

    public void desligar() {
    }

    public void mudarCanal(int canal) {
    }

    public void pause() {
    }

    public void start() {
    }

    public void stop() {
    }

    public void semBaterias() {
    }

}

public class ComandoBox implements ComandoUniversal2 {

    //métodos herdados pela interface ComandoUniversal2
    public void ligar() {
    }

    public void desligar() {
    }

    void mudarCanal(int canal) {
    }

    void pause() {
    }

    public void start() {
    }

    public void stop() {
    }

    public void semBaterias() {
    }

    //método extra definido na interface ComandoUniversal2
    public int mostrarCanal() {
    }
}

//Esta classe, sem a implementação dos métodos, provocará um erro de compilação.
public class ComandoErrado implements ComandoUniversal {
    //sem qualquer implementação
}

//Nesta classe faltam dois métodos, logo terá de ser uma classe abstracta e os dois métodos em 
//falta terão de ser implementados numa sub-classe
public class ComandoAbstracto implements ComandoUniversal {

    public void ligar() {
    }

    public void desligar() {
    }

    public void mudarCanal(int canal) {
    }

    public void pause() {
    }

    public void start() {
    }
}

//Esta sub-classe implementa os dois métodos em falta na classe mãe.
//Devido ao mecanismo de herança, esta classe também implementa a interface ComandoUniversal
public class Comando extends ComandoAbstacto {

    public void stop() {
    }

    public void semBaterias() {
    }
}

  1. Tipos internos são classes definidas dentro de classes, ou interfaces neste caso 

  2. O sistema de serialização poderá obrigar a implementar dois métodos especiais, mas esses métodos não estão definidos na interface Serializable