1. Habilidades

Para entender melhor os benefícios das interfaces e onde usá-las, precisamos falar sobre algumas coisas mais abstratas.

Uma classe geralmente modela um objeto específico. Uma interface corresponde menos a objetos e mais a suas habilidades ou funções.

A essência das interfaces

Por exemplo, coisas como carros, bicicletas, motocicletas e rodas são melhor representadas como classes e objetos. Mas suas habilidades - como "Posso ser montado", "Posso transportar pessoas", "Posso ficar de pé" - são melhor apresentadas como interfaces. aqui estão alguns exemplos:

Código Descrição
interface CanMove
{
   void move(String newLocation);
}
Corresponde à capacidade de movimento
interface Rideable
{
   void ride(Passenger passenger);
}
Corresponde à capacidade de ser montado
interface CanTransport
{
   void addStuff(Object stuff);
   Object removeStuff();
}
Corresponde à capacidade de transportar coisas
class Wheel implements CanMove
{
   ...
}
A Wheelclasse pode se mover
class Car implements CanMove, Rideable, CanTransport
{
   ...
}
A Carclasse pode se mover, ser montada e transportar coisas
class Skateboard implements CanMove, Rideable
{
   ...
}
A Skateboardclasse pode se mover e ser montada


2. Funções

Interfaces simplificam muito a vida de um programador. Muitas vezes, um programa tem milhares de objetos, centenas de classes, mas apenas algumas dezenas de interfaces , ou seja, funções . Existem poucos papéis, mas existem muitas maneiras de combiná-los (classes).

O ponto principal é que você não precisa escrever código em cada classe para interagir com todas as outras classes. Você só precisa interagir com suas funções (interfaces).

Imagine que você é um treinador de animais de estimação. Cada um dos animais de estimação com os quais você trabalha pode ter várias habilidades diferentes. Você entra em uma discussão amigável com seu vizinho sobre quais animais de estimação podem fazer mais barulho. Para resolver o problema, basta alinhar todos os bichinhos que podem "falar" e dar a eles o comando: Fale!

Você não se importa que tipo de animal eles são ou que outras habilidades eles têm. Mesmo que eles possam dar uma cambalhota tripla para trás. Neste momento específico, você está interessado apenas em sua capacidade de falar alto. Veja como ficaria no código:

Código Descrição
interface CanSpeak
{
   void speak();
}
A CanSpeakhabilidade. Essa interface entende o comando to speak, o que significa que possui um método correspondente.
class Cat implements CanSpeak
{
   void speak()
   {
      println("MEOW");
   }
}

class Dog implements CanSpeak
{
   void speak()
   {
      println("WOOF");
   }
}

class Fish
{
   ...
}
Animais que possuem esta característica.

Para facilitar o entendimento, disponibilizamos os nomes das turmas em inglês. Isso é permitido em Java, mas é altamente indesejável.













Nosso Fishnão tem a capacidade de falar (não implementa a CanSpeakinterface).

public static void main(String[] args)
{
   // Add all the animals to the list
   ArrayList pets = new ArrayList();
   pets.add(new Cat());
   pets.add(new Dog());
   pets.add(new Fish());

   // If the ability exists, then make a sound
   for(Object pet: pets)
   {
      if (pet instanceof CanSpeak)
      {
         CanSpeak loudmouth = (CanSpeak) pet;
         loudmouth.speak();
      }
   }
}
E como damos a eles o comando?

Quando o número de aulas em seus programas chegar aos milhares, você não conseguirá viver sem interfaces. Em vez de descrever a interação de milhares de classes, basta descrever a interação de algumas dezenas de interfaces — isso simplifica muito a vida.

E quando combinada com o polimorfismo, essa abordagem geralmente é um sucesso estrondoso.



3. A defaultimplementação de métodos de interface

Classes abstratas podem ter variáveis ​​e implementações de métodos, mas não podem ter herança múltipla. As interfaces não podem ter variáveis ​​ou implementações de métodos, mas podem ter herança múltipla.

A situação é expressa na tabela a seguir:

Habilidade/propriedade aulas abstratas Interfaces
Variáveis
Implementação do método
Herança múltipla

Portanto, alguns programadores realmente queriam que as interfaces tivessem a capacidade de ter implementações de método. Mas ter a capacidade de adicionar uma implementação de método não significa que um sempre será adicionado. Adicione se quiser. Ou se você não fizer isso, então não faça.

Além disso, os problemas com herança múltipla são principalmente devidos a variáveis. De qualquer forma, foi o que eles decidiram e fizeram. A partir do JDK 8, o Java introduziu a capacidade de adicionar implementações de método às interfaces.

Aqui está uma tabela atualizada (para JDK 8 e superior):

Habilidade/propriedade aulas abstratas Interfaces
Variáveis
Implementação do método
Herança múltipla

Agora, para classes abstratas e também para interfaces, você pode declarar métodos com ou sem implementação. E esta é uma excelente notícia!

Nas classes abstratas, os métodos sem implementação devem ser precedidos pela abstractpalavra-chave. Você não precisa adicionar nada antes dos métodos com uma implementação. Nas interfaces, o oposto é verdadeiro. Se um método não tiver uma implementação, nada deverá ser adicionado. Mas se houver uma implementação, a defaultpalavra-chave deve ser adicionada.

Para simplificar, apresentamos essas informações na tabelinha a seguir:

Habilidade/propriedade aulas abstratas Interfaces
Métodos sem implementação abstract
Métodos com uma implementação default

Problema

O uso de interfaces que possuem métodos pode simplificar muito as hierarquias de classes grandes. Por exemplo, o resumo InputStreame OutputStreamas classes podem ser declarados como interfaces! Isso nos permite usá-los com muito mais frequência e de maneira muito mais conveniente.

Mas já existem dezenas de milhões (bilhões?) de classes Java no mundo. E se você começar a alterar as bibliotecas padrão, poderá quebrar alguma coisa. Como tudo! 😛

Para não interromper acidentalmente os programas e bibliotecas existentes, foi decidido que as implementações de métodos em interfaces teriam a menor precedência de herança .

Por exemplo, se uma interface herda outra interface que possui um método e a primeira interface declara o mesmo método, mas sem uma implementação, a implementação do método da interface herdada não alcançará a interface herdada. Exemplo:

interface Pet
{
   default void meow()
   {
      System.out.println("Meow");
   }
}

interface Cat extends Pet
{
   void meow(); // Here we override the default implementation by omitting an implementation
}

class Tom implements Cat
{
}

O código não compilará porque a Tomclasse não implementa o meow()método.