%cabeçalho para todos os capítulos
%\input{cabecalho}

%\begin{document}

%Opções para o pacote listings
%\input{listingOptions}

\chapter{Interfaces}

\begin{center}
\shabox{
  \begin{Bitemize}
    \item[]\textbf{Quais novidades veremos nesta aula?}
    \item Interfaces
  \end{Bitemize}
} % \shabox
\end{center}
\bigskip

\section{O Conceito de Interfaces}

Um dos conceitos principais de orientação a objetos é o \emph{encapsulamento},
através do qual, tanto os atributos quanto a implementação dos métodos de uma certa
classe não são visíveis ao usuário da classe. Conhecendo-se apenas a
\emph{interface} de uma classe, isto é, os métodos disponíveis e suas
respectivas assinaturas, podemos utilizar objetos desta classe sem
conhecer detalhes de como ela é implementada internamente.

Além disto, existem casos, onde existe a necessidade de se ter uma
classe mas não queremos implementá-la. Neste caso, pode-se terceirizar a
implementação, fornecendo como especificação a interface desejada.


\section{Um primeiro exemplo}

Vejamos um exemplo prático: você tem a missão de criar um zoológico
virtual com vários tipos de animais. Você gostaria de enviar as
seguintes mensagens a cada animal:

\begin{itemize}
\item \texttt{nasça()};
\item \texttt{passeiePelaTela()};
\item \texttt{durma()};
\end{itemize}

Mas, apesar de você ser especialista em computação você conhece muito pouco a
respeito de animais, logo você terá que pedir a outros programadores, que
conhecem bem os animais, as seguintes classes: \texttt{Ornitorrinco},
\texttt{Morcego} e \texttt{Zebra}. Neste caso, você passará a seguinte
especificação:

\begin{lstlisting}
interface Animal
{
   void nasça();
   void passeiePelaTela();
   void durma();
   double peso();
}
\end{lstlisting}

O programador que for implementar o morcego terá que dizer
explicitamente que vai usar a interface \texttt{Animal}, isto é feito através da
palavra chave \texttt{implements}. Como o objetivo é de apresentar como funcionam
as interfaces, o código dos animais será apenas composto de comandos de
impressão de mensagens.

\begin{lstlisting}
public class Morcego implements Animal
{
   public void nasça()
   {
     System.out.println("Nasce um lindo morcego");
   }
   public void passeiePelaTela()
   {
     System.out.println("Voa de um lado para o outro");
   }
   public void durma()
   {
     System.out.println("Dorme de ponta cabeça");
   }
   public double peso()
   {
     return 4.5; // morcegão :-)
   }
}
\end{lstlisting}

A palavra chave \texttt{implements} obriga o programador a escrever o código
correspondente a todos os métodos com suas respectivas assinaturas. Além
disto, todos os métodos da interface devem ser obrigatoriamente
públicos. Vejamos as implementações das outras classes:

\begin{lstlisting}
public class Ornitorrinco implements Animal
{
   double peso;

   Ornitorrinco (double p)
   {
     peso = p;
   }

   public double peso()
   {
     return peso; 
   }
   public void nasça()
   {
     System.out.println("Quebra o ovo para sair");
   }
   public void passeiePelaTela()
   {
     System.out.println("Anda e nada de um lado para o outro");
   }
   public void durma()
   {
     System.out.println("Dorme dentro de túneis, durante o dia");
   }
}

public class Zebra implements Animal
{
   int listras;
   double peso;

   public Zebra(int l, double p)
   {
      listras = l; // cria uma zebra com l listras
      peso = p     // e peso p
   }
   public void nasça()
   {
     System.out.println("Nasce mais uma zebra");
   }
   public void passeiePelaTela()
   {
     System.out.println("Galopa pelo campo");
   }
   public void durma()
   {
     System.out.println("Dorme em pé");
   }
   public double peso()
   {
     return peso; 
   }
   // nada impede que sejam implementados métodos adicionais
   public void contaListras()
   {
     System.out.println("Esta zebra tem " + l + " listras  " );
   }
}
\end{lstlisting}

\paragraph{Em tempo}. Existe uma regra em Java com relação ao número de classes
públicas que podem existir em um arquivo .java. Em cada arquivo deve
existir no máximo uma classe pública, sendo que caso exista uma, o nome
do arquivo deve ser igual ao nome da classe pública. Logo, no exemplo
acima, as classes \texttt{Ornitorrinco}, \texttt{Morcego} e \texttt{Zebra} devem estar
em arquivos separados, com respectivos nomes: Ornitorrinco.java, Morcego.java e
Zebra.java.

Mas, o uso da interface é um pouco mais amplo, podemos considerar que
cada um dos animais além de ser um objeto da própria classe também é um
objeto do tipo \texttt{Animal}. É interessante ressaltar que não podemos criar
novos objetos a partir da interface \texttt{Animal}. Vejamos mais um exemplo:

\begin{lstlisting}
class ZoologicoVirtual
{
  static public void cicloDeVida(Animal animal)
  {
    animal.nasça();
    animal.passeiePelaTela();
    animal.durma();
  }

  static public void fazFuncionar()
  {
    Zebra        z1 = new Zebra(102);  // cria duas zebras
    Animal       z2 = new Zebra(101);  // sendo uma do tipo Animal
    Morcego      m1 = new Morcego();
    Ornitorrinco o1 = new Ornitorrinco();

    cicloDeVida(z1);
    cicloDeVida(z2);
    cicloDeVida(m1);
    cicloDeVida(o1);
  }
}
\end{lstlisting}

Veja o exemplo do painel de iterações abaixo:

\begin{verbatim}
> ZoologicoVirtual.fazFuncionar()
Nasce mais uma zebra
Galopa pelo campo
Dorme de pé
Nasce mais uma zebra
Galopa pelo campo
Dorme de pé
Nasce um lindo morcego
Voa de um lado para o outro
Dorme de ponta cabeça
Quebra o ovo para sair
Anda e nada de um lado para o outro
Dentro de túneis, durante o dia
>
\end{verbatim}

Observe que apesar de \texttt{z2} ter sido definido como uma nova \texttt{Zebra}, a
referência é para um objeto do tipo \texttt{Animal}, logo chamadas do tipo
{z2.contaListras()}; não são válidas, mas chamadas a \texttt{z1.contaListras()} são.

Na verdade, seria interessante refatorarmos o método \texttt{fazFuncionar}, da seguinte forma.

\begin{lstlisting}

  static public void fazFuncionar()
  {
    Animal [] bicharada = new Animal [4];
    bicharada[0] = new Zebra(102);  
    bicharada[1] = new Zebra(101);  
    bicharada[2] = new Morcego();
    bicharada[3] = new Ornitorrinco();

    for (int i = 0; i < bicharada.length; i++)
      cicloDeVida(bicharada[i]);
  }

\end{lstlisting}

Ficou bem melhor, não?

\section{Implementando mais de uma interface por vez}

Vimos acima que podemos ver objetos como sendo do mesmo tipo, desde que
eles implementem a mesma interface. Isto também é válido no caso de
objetos implementarem várias interfaces (pensando no mundo real isto
acontece muito mais freqüentemente). Vejam as duas interfaces seguintes:

\begin{lstlisting}
interface Voador
{
  void voa();
  void aterrissa();
}

interface TransportadorDePessoas
{
  void entramPessoas();
  void saemPessoas();
}
\end{lstlisting}

Agora vamos pensar em três classes: \texttt{Ave}, \texttt{Onibus} e \texttt{Aviao}. As
classes \texttt{Ave} e \texttt{Onibus} podem implementar a primeira e segunda interface,
respectivamente.

\begin{lstlisting}
class Ave implements Voador
{
  public void voa()
  {
    System.out.println("Bate as asas bem forte");
  }
  public void aterrissa()
  {
    System.out.println("Bate as asas mais fraco e põe os pés no chão");
  }
}

class Onibus implements TransportadorDePessoas
{
  public void entramPessoas()
  {
    System.out.println("Abre as portas e entram as pessoas");
  }
  public void saemPessoas()
  {
    System.out.println("Abre as portas e saem as pessoas");
  }
}
\end{lstlisting}

Finalmente, podemos ver o \texttt{Aviao} que implementa as duas interfaces:

\begin{lstlisting}
class Aviao implements Voador, TransportadorDePessoas
{
  public void voa()
  {
    System.out.println("Liga as turbinas; recolhe o trem de pouso");
  }
  public void aterrissa()
  {
    System.out.println("Abaixa o trem de pouso e desce");
  }
  public void entramPessoas()
  {
    System.out.println("Procedimento de embarque");
  }
  public void saemPessoas()
  {
    System.out.println("Procedimento de desembarque");
  }
}
\end{lstlisting}

Observe o trecho abaixo:

\begin{lstlisting}
public class TesteDeInterface
{
  static public void faz()
  {
    TransportadorDePessoas t = new Onibus();
    Voador v = new Ave();
    Avião  a = new Aviao();

    t.entramPessoas();
    t.saemPessoas();
    v.voa();        // bate asas
    v.aterrissa();
    // Com o Onibus e Ave não podemos chamar a outra interface.
    a.entramPessoas();
    a.voa();
    a.aterrissa();
    a.saemPessoas();
    v = a;
    v.voa();        // liga turbinas
  }
}
\end{lstlisting}

Uma boa prática seguida por bons programadores OO é ``Programe para as
interfaces, não para as implementações''. Em outras palavras, toda vez em
que você escrever código que utiliza outras classes, não pense em como
essas outras classes são implementadas internamente, pense apenas na sua
interface. Nunca baseie o seu código em alguma idiossincrazia interna da
classe, use apenas conceitos que são claros a partir da interfaces das
classes que você usa.

\section{Um exemplo mais sofisticado}

Vamos supor que temos uma classe \texttt{Fruta} com os seguintes atributos:
\texttt{peso}, \texttt{valor} e \texttt{nome}. Os três atributos já devem ser
carregados no construtor.

\begin{lstlisting}
class Fruta
{
  double peso;
  double valor;
  String nome;

  Fruta(String n, double v, double p)
  {
    nome  = n;
    valor = v;
    peso  = p;
  }

  void imprime()
  {
    System.out.println(nome + " pesa " + peso
                       + "g e custa " + valor + "reais");
  }
}
\end{lstlisting}

Queremos criar um vetor de \texttt{Fruta}s e ordena-lo primeiro por
\texttt{valor} e posteriormente por \texttt{peso}. Como fazer isto? Observando os
procedimentos de ordenação já vistos é fácil ver que a única mudança é o
critério de comparação. Veja uma implementação usando o algoritmo de inserção
direta visto no Capítulo \ref{cap:busca-ordenacao}.

\begin{lstlisting}
public class Quitanda
{
   Fruta []frutas = new Fruta[5];

   public Quitanda()
   {
     frutas[0] = new Fruta("Laranja", 0.5, 100);
     frutas[1] = new Fruta("Maça", 0.8, 120);
     frutas[2] = new Fruta("Mamão", 1.2, 110);
     frutas[3] = new Fruta("Cereja", 5.0, 20);
     frutas[4] = new Fruta("Jaca", 0.4, 500);
   }

   public void imprime()
   {
     for(int i = 0; i < frutas.length; i++)
       frutas[i].imprime();
   }

   public void ordenaPorValor()
   {
     int i, j;
     Fruta aInserir;

     for (i = 1; i < frutas.length; i++)
     {
       aInserir = frutas[i];
       j = i;
       while((j > 0) && (frutas[j-1].valor > aInserir.valor))
       {
          frutas[j] = frutas[j-1];
          j--;
       }
       frutas[j] = aInserir;
     }
   }

   public void ordenaPorPeso()
   {
     int i, j;
     Fruta aInserir;

     for (i = 1; i < frutas.length; i++)
     {
       aInserir = frutas[i];
       j = i;
       while((j > 0) && (frutas[j-1].peso > aInserir.peso))
       {
          frutas[j] = frutas[j-1];
          j--;
       }
       frutas[j] = aInserir;
     }
   }

   public static void main(String [] args)
   {
     Quitanda xepa = new Quitanda();

     System.out.println("Desordenado");
     xepa.imprime();
     System.out.println("Em ordem de valor");
     xepa.ordenaPreco();
     xepa.imprime();
     System.out.println("Em ordem de peso");
     xepa.ordenaPeso();
     xepa.imprime();
   }
}
\end{lstlisting}

No programa acima, fica claro que tivemos que duplicar o código de ordenação,
o que é bem desagradável. Mas, e se existissem outros critérios para
ordenação, teríamos que criar um novo método repetindo o código de ordenação
para cada um dos critérios? Isso seria, com certeza, muito ruim. 

Como regra geral, devemos sempre evitar código repetido. Quando identificamos
um trecho de código que aparece repetido em vários lugares, como no caso
acima, devemos tentar refatorar (reorganizar) o código para evitar a
repetição. Neste caso, iremos manter o código de ordenação em apenas um método
e colocar em outros métodos apenas aquele pequeno trecho que difere de um para
outro (o critério de comparação). Para implementar esta nova solução,
utilizaremos uma \texttt{interface} definindo a interface de comparação:

\begin{lstlisting}
interface ComparadorDeFrutas
{
  boolean éMenor(Fruta a, Fruta b);
}
\end{lstlisting}

O significado do método é óbvio: se \texttt{a} for menor que \texttt{b}, o método
devolve \texttt{true}, caso contrário, devolve \texttt{false}. O que a
interface \texttt{ComparadorDeFrutas} não define é o significado da palavra
``menor''. Isso é deixado para cada classe concreta que irá implementar esta
interface como vemos abaixo onde são definidas três implementações diferentes
para \texttt{ComparadorDeFrutas} que utilizam, como critério de comparação, o
peso, o valor e o nome da fruta, respectivamente.

\begin{lstlisting}
class ComparaPeso implements ComparadorDeFrutas
{
  public boolean éMenor(Fruta a, Fruta b){ return (a.peso < b.peso);}
}

class ComparaValor implements ComparadorDeFrutas
{
  public boolean éMenor(Fruta a, Fruta b){ return (a.valor < b.valor);}
}

class ComparaNome implements ComparadorDeFrutas
{
  public boolean éMenor(Fruta a, Fruta b){ return (a.nome.compareTo(b.nome) == -1);}
}

\end{lstlisting}

Agora, basta colocar como parâmetro adicional do método de ordenação o
comparador desejado:

\begin{lstlisting}
public class Quitanda
{
    Fruta []frutas = new Fruta[5];

    public Quitanda()
    {
      frutas[0] = new Fruta("Laranja", 0.5, 100);
      frutas[1] = new Fruta("Maça", 0.8, 120);
      frutas[2] = new Fruta("Mamão", 1.2, 110);
      frutas[3] = new Fruta("Cereja", 5.0, 20);
      frutas[4] = new Fruta("Jaca", 0.4, 500);
    }

    public void imprime()
    {
      for(int i = 0; i < frutas.length; i++)
        frutas[i].imprime();
    }

    public void ordena(ComparadorDeFrutas c)
    {
      int i, j;
      Fruta aInserir;

      for (i = 1; i < frutas.length; i++)
      {
        aInserir = frutas[i];
        j = i;
        while((j > 0) && (c.éMenor(frutas[j-1], aInserir)))
          {
            frutas[j] = frutas[j-1];
            j--;
        }
        frutas[j] = aInserir;
      }
    }

    public static void main(String [] args)
    {
      Quitanda xepa = new Quitanda();

      System.out.println("Frutas desordenadas");
      xepa.imprime();

      System.out.println("Em ordem de valor:");
      ComparadorDeFrutas cmp = new ComparaValor();
      xepa.ordena(cmp);
      xepa.imprime();
      System.out.println("Em ordem de peso:");
      cmp = new ComparaPeso();
      xepa.ordena(cmp);
      xepa.imprime();
      System.out.println("Em ordem alfabética:");
      xepa.ordena(new ComparaNome()); // note esta forma super-condensada.
      xepa.imprime();
    }
}
\end{lstlisting}

\section{A Importância de Interfaces}

O conceito de interfaces na programação orientada a objetos é muito importante
e o seu uso adequado trás inúmeras vantagens no desenvolvimento de sistemas
grandes e complexos. Eis algumas dessas vantagens:

\begin{enumerate}
\item Se os objetos interagem entre si através de referências a interfaces e
  não a classes específicas, fica fácil mudar as classes utilizadas em um
  sistema sem interferir com aquelas que as utilizam.  Por exemplo, se uma
  classe implementa uma certa interface, mudanças na implementação da classe
  que não alterem a assinatura dos métodos desta interface não são notadas
  quando da utilização de objetos através desta interface.

\item Fica fácil implementar algo chamado \emph{polimorfismo de
    comportamento}, ou seja, podemos utilizar em diferentes momentos classes
  com diferentes comportamentos, chaveando de um comportamento quando for
  necessário. O uso de interfaces permite que este chaveamento seja feito
  tanto quando o programa é compilado quanto durante a sua execução. O
  exercício do berçário (veja a seção de exercícios a seguir) é um exemplo
  deste polimorfismo onde interfaces são utilizadas para tornar um programa
  multilingüe, ou seja, com muito pouco esforço pode-se escolher em qual
  língua (português, inglês, francês, etc.) um programa ou sistema utilizará
  para interagir com seus usuários.
\item Se se está desenvolvendo um programa ou sistema muito grande e complexo,
  pode ser necessário utilizar vários programadores ou, até mesmo, várias
  equipes de programadores. Neste caso, o que se costuma fazer é dividir o
  sistema em sub-sistemas e definir muito bem as interfaces de cada
  sub-sistema. A partir daí, cada equipe pode desenvolver independentemente o
  seu sub-sistema sem necessitar de conhecimentos sobre o funcionamento
  interno dos outros sub-sistemas; basta conhecer as suas interfaces. Após
  esta fase, passa-se à fase de integração, durante a qual os vários sub-sistemas
  são compilados, executados e testados em conjunto.
\item O uso de interfaces pode ajudar a eliminar código repetido (como no
  exemplo anterior do \texttt{ComparadorDeFrutas}), o que
  ajuda a melhorar em muito a qualidade do código.
\item Usando-se interfaces, é possível encomendar a terceiros a escrita de
  partes de um programa sem que esta pessoa tenha que conhecer o resto do
  programa ou mesmo ter acesso ao seu código-fonte. Veja um exemplo desta
  prática no exercício das figuras geométricas abaixo, que se utiliza de uma
  interface \texttt{Figura2D}. 
\end{enumerate}



\section{Exercícios:}

\begin{enumerate}

% Exercício 1
\item Seu chefe está fazendo um programa para manipulação de
  figuras geométricas. Como o programa é muito complexo, ele pediu a sua ajuda
  encomendando a você a implementação de três classes (\texttt{Quadrado}, \texttt{Retângulo} e
  \texttt{Círculo}). Você é livre para definir como será a implementação mas
  seu chefe definiu que as suas classes devem implementar as seguintes interfaces:

\begin{lstlisting}
 interface Figura2D
 {
    double calculaÁrea();
    double calculaPerímetro();
    void   mudaCor(String cor);
    String pegaCor();
 }
\end{lstlisting}

% Exercício 2
\item Escreva duas implementações para a interface \texttt{VeículoDeCorrida}, a seguir:

\begin{lstlisting}
interface VeículoDeCorrida
{
    String marca ();
    String modelo ();
    String cor();
    int potênciaEmCavalos ();
}
\end{lstlisting}

Agora, escreva um método \texttt{veículoPreferido()} que recebe um \emph{array} de
veículos de corrida como parâmetro e dentre os veículos vermelhos,
imprime a marca e o modelo do que possuir a maior potência.

% Exercício 3
\item Você foi contratado para trabalhar em um berçário (!!!) e no seu
primeiro dia de trabalho, deve escrever uma classe para informar aos
pais, dados sobre os seus bebês. A dificuldade é que muitos estrangeiros
freqüentam esse berçário e o seu programa deve ser capaz de dar
informações em português e em inglês (e, futuramente, em outros idiomas
também). Para permitir isso, você deverá prover duas implementações da
interface a seguir, que indica as mensagens de texto que deverão ser
mostradas aos pais:

\begin{lstlisting}
interface MensagensSobreNeoNatal
{
   String nomeDoBebê (String nome);
   String dataDeNascimento (Bebê b);
   String peso (double pesoEmQuilos);
   String temperatura (double temperaturaEmCelsius);
}
\end{lstlisting}

Ao se chamar o método \texttt{nomeDoBebê}, por exemplo, sua implementação deve
devolver uma mensagem como "O nome do bebê é Godofredo Manoelino de
Moraes". Ao se chamar o método \texttt{peso}, deve-se devolver algo
como "O peso do bebê é 3140 gramas ". A primeira implementação deve se
chamar MensagensBrasileiras e a segunda MensagensEstadosunidenses. As
mensagens para os americanos devem apresentar o peso em libras
(\emph{pounds}) e a temperatura em graus fahrenheit. A interface Bebê (que
vocês não precisam implementar pois podem supor que o berçario já possui as
implementações), é a seguinte:

\begin{lstlisting}
interface Bebê
{
   String nome();
   int diaNascimento ();
   int mesNascimento ();
   int anoNascimento ();
   double peso (); // SI, ou seja, em quilos
   double temperatura (); // SI, ou seja, em celsius
}
\end{lstlisting}

A classe que o berçário vai usar para imprimir as informações para os
pais terá um método similar ao seguinte:

\begin{lstlisting}
class Berçario
{
 Bebe [] ListaDeBebês;

 // aqui vão outros métodos para inserção e
 // remoção de bebês da lista

 void imprimeDadosSobreBebe (Bebê b, MensagensSobreNeoNatal m)
 {
    System.out.println (m.nomeDoBebê (b.nome ());
    System.out.println (m.dataDeNascimento (b);
    System.out.println (m.peso (b.peso ());
    System.out.println (m.temperatura (b.temperatura ());
 }

 void imprime (int IDdoBebê, String idioma)
 {
    MensagensSobreNeoNatal m;
    if (idioma.equals ("Português"))
       m = new MensagensBrasileiras ();
    else
       m = new MensagensEstadosunidenses ();

    imprimeDadosSobreBebe (bebes[IDdoBebe], m);
 }
}
\end{lstlisting}

% Exercício 4
\item Dada a classe

\begin{lstlisting}
class Pessoa
{
  String nome;
  int rg;
  int cpf;
}
\end{lstlisting}

escreva duas implementações da interface

\begin{lstlisting}
interface LocalizadorDePessoas
{
  Pessoa localizaPorRG (int rg, Pessoa []vp);
}
\end{lstlisting}

utilizando busca seqüencial e busca binária.

\item Refatore o método \texttt{ZoologicoVirtual.fazFuncionar()} de forma a
  usar a classe SavitchIn para permitir que um usuário crie interativamente
  uma coleção de animais virtuais de diferentes tipos.


\item (Longo) Você foi contratado para ajudar na implementação de uma loja virtual
  para venda, através da Web, de livros, CDs, LPs, DVDs, filmes VHS, etc. No
  seu primeiro dia de trabalho, seu chefe lhe mostrou a seguinte interface que
  é utilizada para representar todos os produtos a serem vendidos pela loja:
\begin{verbatim}
interface Produto
{
  String título(); 
  int    númeroDeIdentificação(); // número único identificando o produto
  int    ano();
  String autor();
  String mídia(); // devolve "livro", "CD", "DVD", etc.
}
\end{verbatim}

No seu primeiro dia de trabalho, você deve implementar uma classe contendo
métodos para:

\begin{enumerate}
\item dada uma lista de compras (um \emph{array} de
  \texttt{Produto}s) devolver uma nova lista de compras contendo o mesmo
  conteúdo mas com os produtos ordenados de acordo com os seus
  \texttt{númerosDeIdentificação};

\item dadas duas listas de compras, cada uma delas já ordenadas
  com o método acima, gerar e devolver uma nova lista ordenada resultante da
  fusão das duas listas iniciais; elementos que aparecerem nas duas listas
  iniciais deverão aparecer duplicados na lista final.

\item Agora, escreva pelos menos duas classes que
  implementem a interface \texttt{Produto} e, em seguida, dê um exemplo de
  código que cria duas listas de compras, as ordena, as funde, e finalmente
  imprime de forma clara e organizada as informações sobre os produtos
  contidos na lista resultante da fusão.
\end{enumerate}


\end{enumerate}

%\end{document}
