Namespaces / Packages

Namespaces / Pacotes

Quando estamos desenvolvendo um programa no Paradigma de Programação Orientado a Objetos, provavelmente iremos criar várias classes. Cada uma dessas classes tem seu próprio nome e, às vezes, iremos colocar um nome que já existe. Isso pode acontecer por conta das classes existentes no C# ou no Java, por conta de classes que outro desenvolvedor esteja criando no mesmo projeto, etc. Por exemplo: vamos supor que, para calcular a média de um aluno, a gente crie uma classe chamada Math e que dentro dela exista um método para calcular médias. O problema é que no C# ou no Java, já existe uma classe com esse nome! Mas, não haverá problemas! Isso porque a classe Math do C# se encontra em um namespace diferente da nossa classe Math. Ou, no Java, ela se encontra em um pacote (package) diferente.

Podemos definir, então, que os namespaces (C#) e os pacotes (Java) servem para organizarmos as nossas classes da mesma forma que diretórios (pastas) servem para organizar nossos arquivos no disco. Essa analogia é importante porque a criação de namespaces/pacotes não serve apenas para evitar conflitos de nomes entre classes. É uma boa prática colocarmos juntas as classes que possuam alguma ligação entre si.

Mas, como criamos um namespace/pacote? Vamos ver um exemplo:

[wptabs]
[wptabtitle]C#[/wptabtitle]
[wptabcontent][code language=”csharp” highlight=”1,2,9″]namespace ExemploDeNamespace
{
public class Program
{
public static void Main(string[] args)
{
}
}
}[/code]

Podemos perceber que, para criar um namespace em C#, usamos a instrução namespace seguido do nome que queremos para esse namespace. Após isso, usamos chaves para definir o que ficará dentro desse namespace.
[/wptabcontent]
[wptabtitle]Java[/wptabtitle]
[wptabcontent][code language=”java” highlight=”1″]package ExemploDePacote;

public class Program {
public static void main(String[] args) {
}
}
[/code]

Podemos perceber que, para criar um pacote em Java, usamos a instrução package seguido do nome que queremos para esse pacote. Após isso, tudo o que estiver no arquivo ficará dentro desse pacote. É importante que esse comando seja a primeira linha do arquivo!

Em Java, existe um relacionamento muito estreito entre os pacotes e os diretórios (pastas) que ficam no disco. Uma classe que está declarada um pacote chamado ExemploDePacote deve ficar em um diretório (pasta) de mesmo nome, da mesma forma que uma classe pública deve ficar em um arquivo de mesmo nome.

No exemplo acima, a classe Program deve estar em um arquivo chamado Program.java. Da mesma forma, ao ser compilada, a classe Program irá gerar um arquivo chamado Program.class que deve estar em um diretório (pasta) de nome ExemploDePacote.
[/wptabcontent]
[/wptabs]

Para usar uma classe que está em determinado namespace/pacote, temos algumas alternativas:

Mesmo namespace/pacote

Esse é o caso mais simples: quando estamos dentro do mesmo namespace/pacote da classe que queremos usar, basta indicar o seu nome normalmente. Assim, se temos uma classe chamada Aluno que usa uma classe chamada Math e elas estão no mesmo namespace/pacote, basta usá-la. Exemplo:

[wptabs]
[wptabtitle]C# – Aluno.cs[/wptabtitle]
[wptabcontent][code language=”csharp” highlight=”1,10″]namespace ExemploDeNamespace
{
public class Aluno
{
public string nome;
public double p1, p2;

public double calculaMedia()
{
Math m = new Math();
double media = m.calculaMedia(p1, p2);
return media;
}
}
}
[/code][/wptabcontent]
[wptabtitle]C# – Math.cs[/wptabtitle]
[wptabcontent][code language=”csharp” highlight=”1″]namespace ExemploDeNamespace
{
public class Math
{
public double calculaMedia(double p1, double p2)
{
return (p1 + p2) / 2;
}
}
}
[/code][/wptabcontent]
[wptabtitle]Java – Aluno.java[/wptabtitle]
[wptabcontent][code language=”java” highlight=”1,8″]package ExemploDePacote;

public class Aluno {
public String nome;
public double p1, p2;

public double calculaMedia() {
Math m = new Math();
double media = m.calculaMedia(p1, p2);
return media;
}
}
[/code][/wptabcontent]
[wptabtitle]Java – Math.java[/wptabtitle]
[wptabcontent][code language=”java” highlight=”1″]package ExemploDePacote;

public class Math {
public double calculaMedia(double n1, double n2) {
return (n1 + n2) / 2;
}
}
[/code][/wptabcontent]
[/wptabs]

Namespaces/Pacotes diferentes

Nesse caso, temos duas opções:

  1. Usar o nome completo da classe, também conhecido como FQN (Fully Qualified Name): o nome completo da classe é composto pelo nome do namespace/pacote seguido de “.” (ponto) seguido do nome da classe. Assim, uma classe chamada Math que está no namespace/pacote chamado util tem, como nome completo, util.Math:

    [wptabs]
    [wptabtitle]C# – Aluno.cs[/wptabtitle]
    [wptabcontent][code language=”csharp” highlight=”1,10″]namespace ExemploDeNamespace
    {
    public class Aluno
    {
    public string nome;
    public double p1, p2;

    public double calculaMedia()
    {
    util.Math m = new util.Math();
    double media = m.calculaMedia(p1, p2);
    return media;
    }
    }
    }
    [/code][/wptabcontent]
    [wptabtitle]C# – Math.cs[/wptabtitle]
    [wptabcontent][code language=”csharp” highlight=”1″]namespace util
    {
    public class Math
    {
    public double calculaMedia(double p1, double p2)
    {
    return (p1 + p2) / 2;
    }
    }
    }
    [/code][/wptabcontent]
    [wptabtitle]Java – Aluno.java[/wptabtitle]
    [wptabcontent][code language=”java” highlight=”1,8″]package ExemploDePacote;

    public class Aluno {
    public String nome;
    public double p1, p2;

    public double calculaMedia() {
    util.Math m = new util.Math();
    double media = m.calculaMedia(p1, p2);
    return media;
    }
    }
    [/code][/wptabcontent]
    [wptabtitle]Java – Math.java[/wptabtitle]
    [wptabcontent][code language=”java” highlight=”1″]package util;

    public class Math {
    public double calculaMedia(double n1, double n2) {
    return (n1 + n2) / 2;
    }
    }
    [/code][/wptabcontent]
    [/wptabs]

  2. Indicar os namespaces/pacotes onde devem ser procuradas as classes: quando usamos o nome completo da classe, precisamos ficar digitando muito código repetitivo. Nesses casos, podemos indicar namespaces/pacotes onde devem ser procuradas as classes que não foram colocadas com o nome completo:

    [wptabs]
    [wptabtitle]C# – Aluno.cs[/wptabtitle]
    [wptabcontent][code language=”csharp” highlight=”1,12″]
    using util;

    namespace ExemploDeNamespace
    {
    public class Aluno
    {
    public string nome;
    public double p1, p2;

    public double calculaMedia()
    {
    Math m = new Math();
    double media = m.calculaMedia(p1, p2);
    return media;
    }
    }
    }
    [/code]

    Podemos perceber que, para indicar que queremos fazer uma busca no namespace util, usamos o comando using seguido do nome desse namespace. Assim, uma classe que não está com o nome completo e não se encontra no mesmo namespace, será procurada no namespace util. É exatamente o caso da classe Math.

    Pode haver mais de um comando desse tipo e é exatamente isso que ocorre no arquivo padrão que o Visual Studio .Net nos fornece quando criamos um novo projeto:

    [code language=”csharp”]
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    [/code]

    Essa é uma lista de namespaces onde se encontram classes muito usadas. É o caso do Console, que se encontra dentro do namespace System. É por esse motivo que podemos usar o comando Console.WriteLine(...) diretamente.
    [/wptabcontent]
    [wptabtitle]C# – Math.cs[/wptabtitle]
    [wptabcontent][code language=”csharp” highlight=”1″]namespace util
    {
    public class Math
    {
    public double calculaMedia(double p1, double p2)
    {
    return (p1 + p2) / 2;
    }
    }
    }
    [/code][/wptabcontent]
    [wptabtitle]Java – Aluno.java[/wptabtitle]
    [wptabcontent][code language=”java” highlight=”3,10″]package ExemploDePacote;

    import util.*;

    public class Aluno {
    public String nome;
    public double p1, p2;

    public double calculaMedia() {
    Math m = new Math();
    double media = m.calculaMedia(p1, p2);
    return media;
    }
    }
    [/code]

    Podemos perceber que, para indicar que queremos fazer uma busca no pacote util, usamos o comando import seguido do nome desse namespace seguindo de .*. Assim, uma classe que não está com o nome completo e não se encontra no mesmo pacote, será procurada no pacote util. É exatamente o caso da classe Math.

    Pode haver mais de um comando desse tipo:

    [code language=”csharp”]
    import java.lang.*;
    import java.util.*;
    import java.io.*;
    import java.text.*;
    [/code]

    Essa é uma lista de pacotes onde se encontram classes muito usadas. É o caso da classe System que se encontra dentro do pacote java.lang. Em especial, o pacote java.lang não precisa ser “importado” explicitamente. O próprio compilador Java está programado para fazê-lo automaticamente. É por esse motivo que podemos usar o comando System.out.println(...) diretamente.
    [/wptabcontent]
    [wptabtitle]Java – Math.java[/wptabtitle]
    [wptabcontent][code language=”java” highlight=”1″]package util;

    public class Math {
    public double calculaMedia(double n1, double n2) {
    return (n1 + n2) / 2;
    }
    }
    [/code][/wptabcontent]
    [/wptabs]

Conflitos

Em alguma situações, conflitos ainda vão ocorrer. É o caso do exemplo dado acima, onde indicamos o namespace/pacote a ser procurado:

[wptabs]
[wptabtitle]C#[/wptabtitle]
[wptabcontent]’Math’ is an ambiguous reference between ‘util.Math’ and ‘System.Math'[/wptabcontent]
[wptabtitle]Java[/wptabtitle]
[wptabcontent]reference to Math is ambiguous both class util.Math in util and class java.lang.Math in java.lang match[/wptabcontent]
[/wptabs]

Ou seja, quando o compilador foi procurar a classe Math, ele a encontrou em nosso namespace/pacote util e em algum outro namespace/pacote.

Para resolver esse conflito, caímos no caso em que devemos usar o nome completo da classe.

Em Java, porém, existe uma outra solução: usar o comando import indicando o nome completo da classe:

[code language=”java” highlight=”3,10″]package ExemploDePacote;

import util.Math;

public class Aluno {
public String nome;
public double p1, p2;

public double calculaMedia() {
Math m = new Math();
double media = m.calculaMedia(p1, p2);
return media;
}
}
[/code]

Nesse caso, o conflito acaba, pois estamos indicando, claramente, qual a classe Math que queremos usar.


Para finalizar, mais algumas informações sobre Java:

  • Você deve ter percebido que podemos usar “.” (ponto) nos nomes dos pacotes. Esses pontos funcionam como separadores de diretórios (pastas). Assim, uma classe que se encontra no pacote br.pro.ramon.exemplo, seu arquivo estará no diretório (pasta) br/pro/ramon/exemplo.
  • A convenção utilizada para dar nomes aos pacotes é usar sempre letras minúsculas.

Espero que tenham gostado de mais esse post. Não se esqueçam de assinar a newsletter que se encontra na barra lateral e de dar uma passadinha no meu canal no YouTube. Nos vemos em breve!

2 pensou em “Namespaces / Pacotes

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *