freeCodeCamp/guide/portuguese/java/interfaces/index.md

11 KiB
Raw Blame History

title localeTitle
Interfaces Interfaces

Interfaces

A interface em Java é um pouco como a Classe, mas com uma diferença significativa: uma interface pode ter assinaturas de métodos, campos e métodos padrão. Desde o Java 8, você também pode criar métodos padrão . No próximo bloco você pode ver um exemplo de interface:

public interface Vehicle { 
    public String licensePlate = ""; 
    public float maxVel 
    public void start(); 
    public void stop(); 
    default void blowHorn(){ 
      System.out.println("Blowing horn"); 
   } 
 } 

A interface acima contém dois campos, dois métodos e um método padrão. Sozinho, não é de muita utilidade, mas geralmente são usados junto com Classes. Como? Simples, você tem que ter certeza que alguma classe o implements .

public class Car implements Vehicle { 
    public void start() { 
        System.out.println("starting engine..."); 
    } 
    public void stop() { 
        System.out.println("stopping engine..."); 
    } 
 } 

:rocket: Executar código

Agora, existe uma regra básica : A classe deve implementar todos os métodos na interface. Os métodos devem ter exatamente a mesma assinatura (nome, parâmetros e exceções) conforme descrito na interface. A classe não precisa declarar os campos, apenas os métodos.

Instâncias de uma interface

Depois de criar uma classe Java que implements qualquer interface, a instância do objeto pode ser referenciada como uma instância da interface. Este conceito é semelhante ao da instanciação de herança.

// following our previous example 
 
 Vehicle tesla = new Car(); 
 
 tesla.start(); // starting engine ... 

Uma interface não pode conter um método construtor, portanto, você não pode criar uma instância de uma interface em si. Você deve criar uma instância de alguma classe implementando uma interface para referenciá-la. Pense em interfaces como um formulário de contrato em branco ou um modelo.

O que você pode fazer com esse recurso? Polimorfismo! Você pode usar apenas interfaces para se referir a instâncias de objetos!

class Truck implements Vehicle { 
    public void start() { 
        System.out.println("starting truck engine..."); 
    } 
    public void stop() { 
        System.out.println("stopping truck engine..."); 
    } 
 } 
 
 class Starter { 
    // static method, can be called without instantiating the class 
    public static void startEngine(Vehicle vehicle) { 
        vehicle.start(); 
    } 
 } 
 
 Vehicle tesla = new Car(); 
 Vehicle tata = new Truck(); 
 
 Starter.startEngine(tesla); // starting engine ... 
 Starter.startEngine(tata); // starting truck engine ... 

:rocket: Executar código

Mas e quanto a múltiplas interfaces?

Sim, você pode implementar várias interfaces em uma única classe. Enquanto em Herança dentro de Classes você estava restrito a herdar apenas uma classe, aqui você pode estender qualquer número de interfaces. Mas não esqueça de implementar todos os métodos de todas as Interfaces, caso contrário a compilação falhará!

public interface GPS { 
    public void getCoordinates(); 
 } 
 
 public interface Radio { 
    public void startRadio(); 
    public void stopRadio(); 
 } 
 
 public class Smartphone implements GPS,Radio { 
    public void getCoordinates() { 
        // return some coordinates 
    } 
    public void startRadio() { 
      // start Radio 
    } 
    public void stopRadio() { 
        // stop Radio 
    } 
 } 

:rocket: Executar código

Algumas características das interfaces

  • Você pode colocar variáveis dentro de uma Interface, embora não seja uma decisão sensata, pois as Classes não estão obrigadas a ter a mesma variável. Em suma, evite colocar variáveis!
  • Todas as variáveis e métodos em uma interface são públicos, mesmo se você deixar de fora a palavra-chave public .
  • Uma interface não pode especificar a implementação de um método específico. Cabe às classes fazer isso. Embora tenha havido uma exceção recente (veja abaixo).
  • Se uma classe implementa múltiplas interfaces, existe uma chance remota de sobreposição de assinatura de método. Como o Java não permite vários métodos da mesma assinatura, isso pode causar problemas. Veja esta pergunta para mais informações.

Métodos padrão de interface

Antes do Java 8, não tínhamos como direcionar uma interface para ter uma implementação de método particular. Isso leva a muita confusão e quebras de código se uma definição de interface for repentinamente alterada.

Suponha que você escreveu uma biblioteca de código aberto, que contém uma interface. Digamos, seus clientes, ou seja, praticamente todos os desenvolvedores em todo o mundo, estão usando muito e estão felizes. Agora você precisou atualizar a biblioteca adicionando uma nova definição de método à Interface para suportar um novo recurso. Mas isso quebraria todas as compilações, já que todas as classes que implementam essa interface precisam mudar agora. Que catástrofe!

Felizmente, o Java 8 agora nos fornece métodos default para Interfaces. Um método default pode conter sua própria implementação diretamente na Interface! Portanto, se uma classe não implementar um método padrão, o compilador executará a implementação mencionada na interface. Bom, não é? Então, em sua biblioteca, você pode adicionar qualquer número de métodos padrão em interfaces sem o medo de quebrar nada!

public interface GPS { 
    public void getCoordinates(); 
    default public void getRoughCoordinates() { 
        // implementation to return coordinates from rough sources 
        // such as wifi & mobile 
        System.out.println("Fetching rough coordinates..."); 
    } 
 } 
 
 public interface Radio { 
    public void startRadio(); 
    public void stopRadio(); 
 } 
 
 public class Smartphone implements GPS,Radio { 
    public void getCoordinates() { 
        // return some coordinates 
    } 
    public void startRadio() { 
      // start Radio 
    } 
    public void stopRadio() { 
        // stop Radio 
    } 
 
    // no implementation of getRoughCoordinates() 
 } 
 
 Smartphone motoG = new Smartphone(); 
 motog.getRoughCoordinates(); // Fetching rough coordinates... 

:rocket: Executar código

Mas o que acontece se duas interfaces tiverem a mesma assinatura de método?

Pergunta impressionante. Nesse caso, se você não fornecer a implementação na classe, o compilador pobre ficará confuso e simplesmente falhará! Você tem que fornecer uma implementação de método padrão dentro da classe também. Há também uma maneira bacana de usar super para chamar de qual implementação você gosta:

public interface Radio { 
    // public void startRadio(); 
    // public void stopRadio(); 
 
    default public void next() { 
        System.out.println("Next from Radio"); 
    } 
 } 
 
 public interface MusicPlayer { 
    // public void start(); 
    // public void pause(); 
    // public void stop(); 
 
    default public void next() { 
        System.out.println("Next from MusicPlayer"); 
    } 
 } 
 
 public class Smartphone implements Radio, MusicPlayer { 
    public void next() { 
        // Suppose you want to call MusicPlayer next 
        MusicPlayer.super.next(); 
    } 
 } 
 
 Smartphone motoG = new Smartphone(); 
 motoG.next(); // Next from MusicPlayer 

:rocket: Executar código

Métodos estáticos em interfaces

Outra novidade no Java 8 é a capacidade de adicionar métodos estáticos a interfaces. Métodos estáticos em interfaces são quase idênticos aos métodos estáticos em classes concretas. A única grande diferença é que os métodos static não são herdados nas classes que implementam a interface. Isso significa que a interface é referenciada ao chamar o método estático e não a classe que o implementa.

interface MusicPlayer { 
  public static void commercial(String sponsor) { 
    System.out.println("Now for a message brought to you by " + sponsor); 
  } 
 
  public void play(); 
 } 
 
 
 class Smartphone implements MusicPlayer { 
    public void play() { 
        System.out.println("Playing from smartphone"); 
    } 
 } 
 
 class Main { 
  public static void main(String[] args) { 
    Smartphone motoG = new Smartphone(); 
    MusicPlayer.commercial("Motorola"); // Called on interface not on implementing class 
    // motoG.commercial("Motorola"); // This would cause a compilation error 
  } 
 } 

:rocket: Executar código

Herdando uma Interface

Também é possível em Java que uma interface herde outra interface, usando, você adivinhou, extends palavra-chave:

public interface Player { 
    public void start(); 
    public void pause(); 
    public void stop(); 
 } 
 
 public interface MusicPlayer extends Player { 
    default public void next() { 
        System.out.println("Next from MusicPlayer"); 
    } 
 } 

Isso significa que a Classe que implementa a Interface MusicPlayer tem que implementar todos os métodos do MusicPlayer , bem como do Player :

public class SmartPhone implements MusicPlayer { 
    public void start() { 
        System.out.println("start"); 
    } 
    public void stop() { 
        System.out.println("stop"); 
    } 
    public void pause() { 
        System.out.println("pause"); 
    } 
 } 

:rocket: Executar código

Ops, eu esqueci o next() ? Veja, já que era um método default , eu não tive que fornecer uma implementação. (Não funciona para JDK <8)

Então, agora você tem uma boa compreensão das Interfaces! Aprenda mais sobre as Classes Abstratas para saber como o Java oferece outra maneira de definir contratos.