Quando importar nomes para o espaço para nome global? (usando x :: y, de x import y etc.)


8

Venho programando em várias linguagens há cerca de 10 anos. E ainda não descobri quando é uma boa ideia importar algo para o espaço de nomes global ( using x::yem C ++, from x import yem Python etc.), por isso quase nunca faço isso.

Quase sempre parece uma má idéia para mim, mesmo que apenas porque limita o conjunto de nomes de variáveis ​​que posso usar. Por exemplo: Onde eu devo usar using namespace std;ou using std::string;em C ++, não posso mais usar stringcomo nome de variável, o que ocasionalmente faço (por exemplo, para funções de utilitário de string).

Mas estou me perguntando: há algumas situações em que a importação de um nome para o espaço de nome global realmente faz sentido? Alguma regra de ouro?


Respostas:


11

Em C ++, geralmente é desaprovado - especialmente using namespace std. Esse stdespaço para nome tem muitos nomes, muitos dos quais são algoritmos muito genéricos, e você pode obter algumas surpresas extremamente desagradáveis ​​quando using namespace std. Algo como using std::cout;não é tão ruim. Mas nunca, nunca, usingnada no espaço de nomes global em um arquivo de cabeçalho. Isso é uma ofensa do esquadrão de tiro.


1
Mas e a minha pergunta? Quando usar x :: y ou importar x de y?
futlib

4

Você deve fazer isso quando simplificar seu código. Você não deve fazer isso quando isso causa conflitos de nomenclatura ou quando pode ser trazido posteriormente para escopos nos quais causa conflitos de nomenclatura, como um arquivo de cabeçalho.

Algumas pessoas pensam que isso deve ser raro. Eu acho que (fora dos arquivos de cabeçalho) não usá-lo deve ser raro, porque o prefixo do espaço para nome geralmente não adiciona nenhuma informação útil, como usar o nome completo de alguém toda vez que você os endereça.

Deixe-me colocar deste jeito. Quando você vê stringcomo um nome de classe, você pensa automaticamente std::stringou mycustom::string? É como o velho ditado. Quando você ouve o som de cascos, pensa em cavalos, não em zebras. Em outras palavras, using namespace stdquase sempre não é grande coisa. using namespace mycustomda mesma forma, geralmente não é um grande problema, a menos que contenha um conflito std; nesse caso, seu namespace personalizado é aquele para o qual você deseja sempre exigir o prefixo.


O que acontece se mycustomcontiver uma stringclasse. No topo você using namespace mycustom;. Através do restante do código que você usa agora string. Todo mundo que lê o código está pensando que std::stringapenas você (e algumas pessoas muito observadoras) estão pensando mycustom::string. Aqui você colocou as zebras no piquete. Consulte também stackoverflow.com/q/1452721/14065
Martin York

1
Você não leu minha última frase? Eu disse especificamente se os mycustomconflitos com stdvocê sempre devem exigir o mycustom::prefixo.
Karl Bielefeldt

Eu fiz. O problema é que a maioria dos namespaces não é trivialmente grande. Saber tudo neles é ainda mais difícil (e versões futuras do espaço para nome podem se expandir). Assim, incluir um espaço para nome inteiro é uma receita para o desastre (usar itens específicos (dentro de um pequeno escopo específico é mais fácil de controlar)). Se o seu código contiver doStuff(int). E uma versão mais recente do mycustomadiciona doStuff(double)todo o significado de qualquer chamada para doStuff(5.5);alterações (potencialmente sem você perceber).
Martin York

3

Trabalhando em Python, uso x import y (como z) constantemente, para ter nomes claros e concisos para fazer referência às importações.

As importações são inestimáveis ​​em uma base de código com uma hierarquia profunda de namespace. Isso ocorre especialmente quando o padrão de estilo da base de código é o PEP 8 , que limita o comprimento da linha a menos de 80 caracteres.

Por exemplo, considere:

import foo

foo.bar.baz.baf.perform_task(foo.bar.baz.quux.SOME_CONSTANT, foo.bar.alice.bob.preferred_hash_function, '42', foo.bar.magic_numbers.MY_SALT)

O que poderia ser escrito:

from foo.bar import baf
from foo.bar.alice import bob
from foo.bar.baz.quux import SOME_CONSTANT
from foo.bar.magic_numbers import MY_SALT

baf.perform_task(SOME_CONSTANT, bob.preferred_hash_function, '42', MY_SALT)

Como os identificadores Python fazem distinção entre maiúsculas e minúsculas e tamanho ilimitado , não ficaremos sem nomes, independentemente de quantos importamos.

Se queremos usar o mesmo nome em nosso módulo como um dos módulos que desejamos importar, podemos usar um alias para a importação:

from foo.bar.alice import bob as carol

def bob(x, y):
    print "running bob function"
    return carol(x, y, 42)

0

Cabe ao programador quando usá-lo. IMHO é melhor não usá-los, especialmente em arquivos de cabeçalho. Mas há vários casos em que eu uso

  • Quando quero introduzir algo em outro espaço para nome, por exemplo

    namespace cg
    {
      namespace details
      {
        //lots of stuff
        void some_cool_foo()
        {
          //uses a lot stuff from details, here because I don't want prefix everything with details::
        }
      }
      using details::some_cool_foo;
    }
  • Para habilitar o ADL para alguns algoritmos de outro espaço para nome

    namespace n1
    {
    //some general foo
    }
    namespace n2
    {
      using n1::foo;
    //some struct
    }
    namespace n3
    {
      using n1::foo;
    //some struct
    }

Se não quiser escrever nomes longos de espaços para nome em .cpp, sempre posso criar um alias

namespace bl = boost::lambda;
namespace fs = boost::filesystem;

desculpe, não poderia fazê-lo destacar minha fonte = /
Kassak
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.