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() {
}
}