8.1 Organizando nossas classes
Por enquanto nossas classes estão todas em um mesmo arquivo, dentro da pasta src. Conforme o projeto vai evoluindo, mais e mais classes são criadas e fica cada vez mais difícil manter a organização de nosso projeto. Mas organização não será o único problema aqui.
Com o passar do tempo, trabalharemos com classes de terceiros (bibliotecas) e classes da própria API da linguagem, o que torna ainda maior o risco de criarmos uma classe com o nome igual a outra existente em alguma dessas bibliotecas.
Quer um exemplo? Poderíamos criar uma classe que se chama Date:
class Date {
java
private int dia;
private int res; private int ano;
// getters e setters
}
Em um método main qualquer de nossa aplicação, poderíamos instan-
ciar essa classe fazendo:
public static void rain(String[] args) { Date date = new Date();
}
Mas na API do Java, já existe uma classe chamada Date. Como a
JVM sabe diferenciar quando precisamos instanciar a nossa classe Date ou quando deve ser o Date do Java? A resposta é bem simples: em Java classes são agrupadas por pacotes (packages).
O pacote da classe Date da API do Java com certeza será diferente do pacote de nossa classe, portanto, para tirar a ambiguidade podemos instanciar a classe pelo seu nome completo, como por exemplo:
public static void rain(String[] args) { java.util.Date date = new java.util.Date();
}
Estranho? Não se preocupe, vamos melhorar a legibilidade desse código
logo. Mas repare que o nome completo da classe, ou fully qualified name como é comumente chamado, é composto por nome do pacote . (ponto) nome da classe. Neste caso, o nome do pacote onde se encontra a classe Date é java.util.
Pacotes da API do Java
Além do java.util, existem diversos pacotes com classes essenciais para nosso dia a dia trabalhando com Java. Algumas classes como a String e System não precisam ser escritas com o nome completo, pois fazem parte do pacote java.lang, que é o pacote padrão do Java. No próximo capítulo estudaremos a fundo o pacote java.lang e, no decorrer do livro, veremos alguns dos demais principais pacotes da API.
Observando o código a seguir você já deve ter sentido uma perda de legibilidade:
java.util.Date date = new java.util.Date();
Podemos simplificar esse código adicionando um import com o nome completo da classe no início de nosso arquivo. Repare:
import java.util.Date;
python
class Teste {
text
public static void main(String[] args) { Date date = new Date();}
}
Só será necessário escrever o nome completo da classe sem um import se
por alguma razão você precisar usar duas classes com o mesmo nome dentro do mesmo arquivo. Nesse caso, você poderá fazer o import de uma delas, mas utilizar o nome completo quando for se referir à outra.
A essa altura você já deve ter se perguntado: Qual o nome completo da nossa classe Date? Como nós criamos a classe diretamente no diretório src, ela não tem um pacote definido. Dizemos que ela está no default package.
Isso não é nada bom, toda classe deve ser agrupada em pacotes. Isso, além de ajudar na organização de nossos projetos, ajudará quando houver uma ambiguidade de nomes.
Nomenclatura padrão dos pacotes Java
Por padrão, um pacote em Java sempre:
• é escrito em letra minúscula (lowercase);
• deve ser um nome de domínio, iniciado com com, edu, gov etc.
http://www.oracle.com/technetwork/java/codeconventions-135099. html
Agora que já sabemos disso, podemos criar alguns pacotes para melhor organizar o nosso projeto. No Eclipse isso pode ser feito pelo menu File
New > Package, ou utilizando o atalho Control + N e selecionando a opção package.
A princípio, criaremos os pacotes:
• br.com.casadocodigo.livraria para as classes Autor e
Editora;
• br.com.casadocodigo.livraria.produtos para as interfaces
Promocional, Produto e suas implementações;
• br.com.casadocodigo.livraria.teste para nossas classes executáveis, ou seja, que possuem o método main.
Antes de mover as classes para seus devidos pacotes, é importante conhecer algumas regras. A primeira delas é que nossas classes devem ser públicas para que fiquem visíveis entre os diferentes pacotes. Logo falaremos mais sobre os modificadores de visibilidade e entenderemos a fundo as suas regras, mas desde já mantenha a regra em mente.
Outro detalhe importante é que, para o caso das classes públicas, o arquivo .java obrigatoriamente tem que ter o nome da classe. Por exemplo, a classe Livro tem que ser salva no arquivo Livro.java. Como vimos no início deste livro, o ideal é você sempre nomear suas classes dessa forma. Essa é considerada uma boa prática em Java.
Agora sim, mãos à massa! Você pode arrastar as classes com o mouse para mover entre pacotes, mas uma alternativa interessante é o atalho Control
- Alt + V. Esse atalhoé equivalente ao menu Refactor > Move…
Vamos selecionar as classes Autor e Editora e mover para o pacote br.com.casadocodigo.livraria. Nesse momento, alguns erros de compilação devem aparecer, mas devemos terminar de mover as classes antes de corrigir qualquer um deles.
Promocional, Produto, Livro, LivroFisico, MiniLivro, Ebook, Revista e qualquer outra implementação de Produto que você tenha criado podem ser movidos para o pacote br.com.casadocodigo.livraria.produtos.
Para terminar, vamos mover as demais classes, que têm um método main, para o pacote br.com.casadocodigo.livraria.testes. Lembre-se, em um projeto real não criaríamos várias classes com método main, só estamos fazendo isso para testar os nossos exemplos.
package, import e possíveis erros
Se você moveu as classes utilizando o Eclipse ou alguma IDE equivalente, repare que foi adicionado um import para toda classe que referencia alguma presente em outro pacote. Caso você não tenha movido pela IDE ou por algum motivo o import não tenha sido adicionado, você precisará fazer isso manualmente como no exemplo:
package br.com.casadocodigo.livraria.testes;
import br.com.casadocodigo.livraria.Autor;
// outros imports
java
public class CadastroDeLivros {
python
public static void main(String[] args) {Autor autor = new Autor(); autor.setNome(“Rodrigo Turini”);
// continua�ao da classe
}
Como a classe Autor está em um pacote ( package) diferente da classe
CadastroDeLivros, o import é necessário. Ele sempre é necessário quando queremos utilizar classes de outros pacotes. E não se esqueça que, para que uma classe seja visível para outro pacote, ela deve ser pública.
Um outro detalhe é que agora todas as classes têm o package a que pertencem declarado. Neste exemplo, o package da classe CadastroDeLivros é:
package br.com.casadocodigo.livraria.testes;
A ordem das instruções de seus arquivos .java agora será: primeiro o package ao qual ela pertence, seguido do(s) import(s) quando necessário e, por último,a declaração da classe.
Importando todas as classes de um package
No lugar de fazer os seguintes imports:
import br.com.casadocodigo.livraria.Autor; import br.com.casadocodigo.livraria.Editora;
Você também pode utilizar o
\*
para importar todas as classes de
um package, neste caso o import seria:
import br.com.casadocodigo.livraria.\*;
É comum ouvirmos que isso prejudica a performance, mas na realidade não afetará o tempo de execução. O problema dessa abordagem é que não previne a ambiguidade de nomes. Por isso, é sempre recomendado que você importe classe a classe, pois, além de evitar problemas com classes de mesmo nome, tornará a legibilidade dos imports mais clara.
Ainda existe um erro de compilação em nosso projeto (ou talvez mais, se o seu código não estiver idêntico ao do livro). Em nosso caso, o problema é na própria classe CadastroDeLivros, quando ela invoca o método mostrarDetalhes do LivroFisico. O erro de compilaçãoéo seguinte:
The method mostrarDetalhes() from the type Livro is not visible
Isso acontece porque, assim como as classes, para que um método seja visível em outro pacote ele precisa ser public. Podemos acessar a classe Livro e adicionar o modificador de visibilidade public no método ou fazer isso pelo atalho Control + 1 do Eclipse (quickfix), selecionando a opção Change visibility of method mostrarDetalhes() to public. No final, o método deve ficar assim:
public void mostrarDetalhes() { System.out.println("Mostrando detalhes do livro "); System.out.println("Nome: " + nome); System.out.println("Descricao: " + descricao);
python
System.out.println("Valor: " + valor); System.out.println("ISBN: " + isbn);if (this.temAutor()) { autor.mostrarDetalhes();
}
System.out.println("--");
python