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

%\begin{document}

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

\chapter{Construtores e especificadores de acesso}

\begin{center}
\shabox{
  \begin{Bitemize}
    \item[]\textbf{Quais novidades veremos nesta aula?}
    \item Construtores
    \item Especificadores de acesso
    \item \texttt{final} e \texttt{static}
  \end{Bitemize}
} % \shabox
\end{center}
\bigskip

\section{Construtores}

Desde o início do curso até agora nós trabalhamos com diversos objetos
diferentes. Mas, antes de começar a usar um objeto de uma classe \texttt{X}, nós
devemos criá-lo. Isto foi feito até agora através de chamadas do tipo:
\texttt{X x = new X();} na qual a variável x passa a se referir a um novo objeto da
classe \texttt{X}.

Na linguagem Java, quando não especificamos como um objeto deve ser
criado, a própria linguagem nos fornece um construtor padrão. Vejamos
com mais detalhes um exemplo abaixo:

\begin{lstlisting}
class Ex1
{
    int a;
    double d;
    String s;
    boolean b;

    void imprime()
    {
    System.out.println("o inteiro vale " + a);
    System.out.println("o real vale " + d);
    System.out.println("a String vale " + s);
    System.out.println("o boolean vale " + b);
    }
    public static void main(String []args)
    {
    Ex1 e = new Ex1();
    e.imprime();
    }
}
\end{lstlisting}

No exemplo acima podemos ver que os números foram inicializados
automaticamente com zero, a \texttt{String} com \texttt{null} e o \texttt{boolean}
com \texttt{false}. A inicialização com a referência nula, \texttt{null} é o padrão para as
referências a objetos em geral.

Mas, e se por alguma razão queremos que as variáveis da classe tenham
algum valor pré-definido, ou melhor ainda, que seja definido durante a
"construção" do objeto. Neste caso podemos definir explicitamente um
construtor. Veja o exemplo abaixo:

\begin{lstlisting}
class Ex2
{
    int a;
    double d;
    String s;
    boolean b;

    Ex2 (int i1, double d1, String s1, boolean b1)
    {
    a = i1;
    d = d1;
    s = s1;
    b = b1;
    }

    void imprime()
    {
    System.out.println("o inteiro vale " + a);
    System.out.println("o real vale " + d);
    System.out.println("a String vale " + s);
    System.out.println("o boolean vale " + b);
    }
    public static void main(String []args)
    {
    // Ex2 e = new Ex2();   ERRO não podemos mais usar o construtor padrão
    Ex2 obj1 = new Ex2(2, 3.14, "Oi", true);
    Ex2 obj2 = new Ex2(1, 1.0, "Tudo 1", true);


    obj1.imprime();
    System.out.println();
    obj2.imprime();
    }
}
\end{lstlisting}

A primeira observação importante é que não podemos mais usar o
construtor padrão. Se a própria classe nos fornece um construtor, é de
se esperar que devamos respeitar algumas regras na hora de construir o
objeto, logo o construtor padrão não está mais disponível.

Podemos também pensar em um exemplo um pouco mais sofisticado, criando
uma classe que representa contas em um banco. Como atributos óbvios
podemos pensar em ter o nome do titular e o saldo de cada conta. É
natural, que não possamos criar contas sem titular, logo no construtor
sempre será necessário fornecer um nome (\texttt{String}).

\begin{lstlisting}
class Conta
{
    String titular;
    double saldo;

    Conta (String s, double val)
    {
    titular = s;
    saldo = val;
    }

    void imprime()
    {
    System.out.println("O cliente: " + titular + " tem saldo " + saldo);
    }
    public static void main(String []args)
    {
    Conta c1 = new Conta("José", 100);
    Conta c2 = new Conta("Maria", 1000);


    c1.imprime();
    System.out.println();
    c2.imprime();
    }
}
\end{lstlisting}

Mesmo no exemplo bem simples acima podemos notar que uma operação usual
é a criação de contas com saldo zero. Logo, parece natural que tenhamos
um construtor que receba apenas o nome, e não o saldo (ficando
subentendido neste caso que não houve depósito inicial).

\begin{lstlisting}
    Conta (String s)
    {
    titular = s;
    saldo = 0;
    }
\end{lstlisting}

Pode-se observar também que podemos reescrever o construtor acima usando
funcionalidades do primeiro construtor.

\begin{lstlisting}
    Conta (String s)
    {
    this( s, 0.0);
    }
\end{lstlisting}

Para isso usamos uma palavra reservada da linguagem Java, a palavra this
que nada mais é do que uma referência ao próprio objeto. Isto é, quando
o construtor \texttt{Conta("João")} é chamado, ele repassa o trabalho ao outro
construtor usando saldo 0.

Também é interessante notar a diferença entre os dois construtores, como
eles tem o mesmo nome (nome da classe), a única diferença entre eles
está nos parâmetros recebidos. O compilador Java escolhe o construtor
correto conforme a assinatura (parâmetros e sua ordem). Esta mesma
técnica também pode ser usada se precisarmos de dois métodos com o mesmo
nome, mas que recebam parâmetros diferentes. Isto é chamado de
polimorfismo de nome.

Também é interessante ressaltar um outro uso da palavra chave \texttt{this}.
Vamos supor que adicionamos um novo parâmetro para as contas, o RG.
Logo, teremos um atributo a mais: \texttt{String RG}. Se por acaso quisermos criar
um novo construtor que receba um parâmetro também chamado de \texttt{RG}, isto se torna
possível.

\begin{lstlisting}
    Conta (String s, double val, String RG)
    {
    titular = s;
    saldo = val;
    this.RG = RG;
    }
\end{lstlisting}

No caso, o \texttt{this} reforça que estamos falando de um dos atributos do
objeto. Até hoje não havíamos usado o \texttt{this} pois tomamos cuidado para
escolher os nomes de parâmetros e variáveis locais diferentes dos nomes
dos atributos.


\section{Especificadores de acesso}

Continuando com o exemplo anterior, poderíamos adicionar métodos seguros
para efetuar depósitos e saques.

\begin{lstlisting}
    void saque(double val)
    {
    if (val <= saldo){
        System.out.println("Saque efetuado com sucesso");
        saldo = saldo - val;
    } else
        System.out.println("Saldo INSUFICIENTE");
        imprime();
    }

    void deposito(double val)
    {
    saldo = saldo + val;
        imprime();
    }
\end{lstlisting}

No código acima, no caso de saque veríamos mensagens avisando sobre o
sucesso ou falha na operação. Existem outras formas mais bonitas de
mostrar as falhas através de Exceções (\texttt{Exceptions}), mas estas fogem ao
escopo deste curso. Entretanto, um usuário poderia autorizar saques
quaisquer, da seguinte forma:

\begin{lstlisting}
Conta c2 = new Conta("Maria", 1000);

c2.imprime();
c2.saldo = c2.saldo - 100000;
c2.imprime();
\end{lstlisting}

Pois, neste caso o usuário do objeto do tipo \texttt{Conta} estaria interagindo
diretamente com atributos do objeto, mexendo nas suas partes internas.
Para evitar isto podemos usar proteções explícitas, indicando que só
métodos do próprio objeto possam alterar os seus atributos. Isto é feito
com a palavra chave \texttt{private}. Se os atributos do Conta forem declarados
da seguinte forma:

\begin{lstlisting}
class Conta
{
    private String titular;
    private double saldo;
    private String RG;
  ...
}
\end{lstlisting}

Não haverá mais acesso direto aos atributos de objetos da classe \texttt{Conta}.
O oposto de \texttt{private} é \texttt{public} que dá acesso irrestrito. Os
especificadores de acesso também podem ser usados com os métodos. Quando
nenhum especificador é utilizado, a linguagem Java usa o acesso
amigável (\emph{friendly}) que só permite a visibilidade dentro do mesmo pacote.

Um outro qualificador interessante é o \texttt{static} que indica quais atributos
devem ser considerados como da classe e não específicos a cada objeto.
Veja o seguinte exemplo:

\begin{lstlisting}
class TesteStatic {
  static int quantidade = 0;

  TesteStatic()
  {
    System.out.println("Criando um objeto do tipo TesteStatic");
    quantidade++;
    System.out.println("Até agora foram criados: " + quantidade + "
                    objetos TesteStatic");
  }
}
\end{lstlisting}

A cada objeto \texttt{TesteStatic} criado veremos quantos objetos deste tipo já
foram criados anteriormente. Observem que não é uma prática usual
colocar impressões no construtor, mas de forma a apresentar um exemplo
simples optamos por tomar esta liberdade. Além disto, métodos \texttt{static}
também são métodos de classe, isto é, podem ser chamados, mesmo que não
existam objetos da classe criados. Um exemplo já visto são as funções da
classe \texttt{Math} como por exemplo \texttt{Math.sin(double x)}. O método
\texttt{main} também é estático pois ao iniciarmos a execução de um programa não existe objeto
criado.

Finalmente, um último qualificador interessante é o \texttt{final} que serve para
definir variáveis que não podem mais ter o seu valor modificado, como
por exemplo \texttt{final double PI = 3.1415926538};

\section{Exercícios}

\begin{enumerate}
\item (difícil): Como fazer para criar uma classe na qual só seja
      possível construir um único objeto. Este tipo de objeto é chamado de \emph{Singleton}.\\
      \emph{Dica:} Limitar o acesso ao construtor.
\end{enumerate}

%\end{document}
