Eu entendo a idéia do escopo do pacote e às vezes até pensei que eu queria. No entanto, toda vez que me empenhava em tentar usá-lo, descobri que não atendia às necessidades que eu pensava que serviriam.
Minha principal questão sempre parece ser que as coisas que desejo limitar o escopo nunca estão no mesmo pacote. Conceitualmente, todos podem estar vinculados, mas a divisão lógica dos dados no aplicativo os possui como pacotes filhos separados de um pacote maior.
Por exemplo, posso ter um modelo de missão e quero que apenas outras ferramentas da missão, como meus serviços de missão, usem alguns métodos. No entanto, acabo com Missions.models e Missions.services como meus pacotes, portanto, MissionModel e MissionService não têm o mesmo escopo de pacote. Nunca parece que existe uma situação em que os pacotes contêm adequadamente o que eu gostaria de ter permissões elevadas, sem incluir também várias coisas que eu não gostaria de ter; e raramente sinto que a vantagem do escopo de pacote de um método justifique a modificação da arquitetura do meu projeto para colocar tudo no mesmo pacote. Freqüentemente, Aspectos ou algum tipo de inversão de controle são a melhor abordagem para qualquer problema que eu considerei brevemente o escopo do pacote.
Estou curioso, pelo contrário, isso geralmente é considerado verdadeiro em todos os desenvolvedores de Java ou é apenas um acaso do trabalho que faço. O escopo do pacote é muito utilizado no mundo real? Existem muitos casos em que é considerado uma boa forma de usar ou é visto principalmente como um comportamento herdado que raramente é explorado no desenvolvimento moderno?
Não estou perguntando nada sobre por que o escopo privado do pacote é padrão; estou perguntando quando ele deve ser usado, independentemente dos padrões. A maioria das discussões sobre por que é padrão não entra realmente quando o escopo do pacote é realmente útil. Em vez disso, argumenta simplesmente por que os outros dois escopos comumente usados não devem ser o padrão, de modo que o pacote vence pelo processo de eliminação. Além disso, minha pergunta é sobre o estado atual de desenvolvimento. Especificamente, desenvolvemos ao ponto em que outras ferramentas e paradigmas tornam o escopo do pacote menos útil do que quando a decisão de torná-lo padrão fazia sentido.
java.util.String
ejava.util.Integer
.Respostas:
Em todo o
java.util.*
pacote, há casos em que o código é escrito com proteção no nível do pacote. Por exemplo, este bit dejava.util.String
+ um construtor em Java 6 :ou este método getChars :
A razão para isso é que os projetistas do código (e
java.util.*
podem ser vistos como uma biblioteca bastante grande) queriam a capacidade de ter um desempenho mais rápido, com o custo de uma perda de várias segurança (verificações de faixa em matrizes, acesso direto a outros campos) que implicam na implementação, e não na interface, acesso 'inseguro' a partes da classe que são consideradas imutáveis por métodos públicos).Ao restringir esses métodos e campos para serem acessados apenas por outras classes no
java.util
pacote, isso facilita o acoplamento entre elas, mas também evita a exposição desses detalhes de implementação ao mundo.Se você está trabalhando em um aplicativo e não precisa se preocupar com outros usuários, a proteção no nível do pacote não é algo com que você precisa se preocupar. Além de vários aspectos da pureza do design, você pode fazer tudo
public
e ficar bem com isso.No entanto, se você estiver trabalhando em uma biblioteca que será usada por outras pessoas (ou quiser evitar emaranhar demais suas classes para refatoração posterior), use o nível mais estrito de proteção oferecido a você para suas necessidades. Muitas vezes isso significa
private
. Às vezes, no entanto, você precisa expor um pouco dos detalhes da implementação a outras classes no mesmo pacote para evitar repetições ou facilitar a implementação real um pouco mais à custa do acoplamento das duas classes e suas implementações. Assim, a proteção no nível do pacote.fonte
Integer.toString()
eString.valueOf(int)
pode compartilhar o código sem expô-lo ao mundo. Asjava.util
classes devem trabalhar em conjunto para fornecer um conjunto maior de funcionalidades, em vez de serem classes individuais que são inteiramente insulares - elas estão juntas em um pacote e compartilham a funcionalidade de implementação por meio do escopo no nível do pacote.Em algum momento, escalo a visibilidade de métodos privados ou protegidos para empacotar para permitir que um teste de junção acesse alguns detalhes da implementação que não devem ser acessados de fora.
como o teste de junção tem o mesmo pacote que o item em teste, ele pode acessar esses detalhes de implementação
exemplo
É discutível se esse é um uso "bom" ou não, mas é pragmático
fonte
protected
ao escopo do pacote?protected
já fornece acesso ao pacote. É uma peculiaridade um pouco estranha, mas acho que eles não queriam exigir declarações de escopo compostas comoprotected packagescope void doSomething()
(que também requer uma nova palavra-chave).Não é tão útil, especialmente como padrão, em um mundo em que as pessoas tendem a usar os nomes pontilhados dos pacotes como se fossem subpacotes. Como o Java não possui subpacote, o xyinternals não tem mais acesso ao xy do que ao ab Os nomes dos pacotes são iguais ou diferentes, uma correspondência parcial não é diferente de não ter nada em comum.
Acho que os desenvolvedores originais nunca esperaram que essa convenção fosse usada e queriam manter as coisas simples sem adicionar a complexidade dos pacotes hierárquicos no estilo Ada.
O Java 9 está tratando disso, pois você pode colocar vários pacotes em um módulo e exportar apenas alguns. Mas isso tornará o escopo do pacote ainda mais redundante.
Em um mundo ideal, eles alterariam o escopo padrão para 'escopo do módulo, se existir um módulo que contenha, caso contrário, o escopo do pacote'. Em seguida, você pode usá-lo para compartilhar a implementação em um módulo, permitindo a refatoração sem interromper as interfaces exportadas. Mas talvez haja alguma sutileza por que isso quebraria a compatibilidade com versões anteriores ou seria ruim.
fonte
O tipo de coesão que você descreve não é realmente o melhor exemplo de onde você usaria o acesso ao pacote. O Package é útil para criar componentes, módulos que são intercambiáveis em uma interface.
Aqui está um exemplo aproximado de um cenário. Suponha que seu código tenha sido reorganizado para ter mais a ver com coesão e componente funcional. Talvez 3 frascos como:
Ao usar o nível do pacote no Mission5000.java, você pode garantir que nenhum outro pacote ou componente como o MissionManager possa unir a implementação da missão. Esse é apenas o componente fornecido por "terceiros" de "M co", na verdade, cria uma implementação de marca especial de uma Missão. O gerente de missão deve chamar MissionBuiler.createMission (...) e usar a interface definida.
Dessa forma, se o componente de implementação da Missão for substituído, sabemos que os implementadores do MissionManager.jar não ignoraram a API e usaram a implementação da MCo diretamente.
Portanto, podemos trocar o MCo-missionizer5000.jar por um produto concorrente. (Ou talvez uma simulação para a unidade de teste do gerente da missão)
Por outro lado, a MCo pode ocultar um pouco de seus segredos comerciais de missionários proprietários.
(Isso também está relacionado à imposição de idéias de instabilidade e abstração nos componentes.)
fonte
Como o escopo do pacote em java não é projetado da maneira hierárquica, dificilmente é útil. Não usamos o escopo do pacote e definimos todas as classes como públicas.
Em vez disso, usamos nossas próprias regras de acesso com base na hierarquia de pacotes e nos nomes de pacotes predefinidos.
Se você estiver interessado em detalhes no google, consulte "CODERU-Rules".
fonte